
توابع یا Functions
یک تابع یک یک فرایندی است که ورودیهایی را به عنوان آرگمان تابع دریافت کرده و خروجیهایی به عنوان مقدار بازگشتی تابع بر میگرداند.توابع میتوانند اهداف زیر را داشته باشند: ۱ـ Mapping یا نگاشت: هدف این توابع تولید خروجی بر پایه مقادیر ورودی یا به عبارتی نگاشت مقادیر ورودی به مقادیر خروجی ۲ـ Procedures یا رویه ها: یک تابع ممکن است فراخوانی شود تا یک دنبالهای از کارهای مختلف را انجام دهد. این دنباله به عنوان یک procedure یا رویه شناخته میشوند و برنامهنویسی به این شیوه را برنامهنویسی procedural یا رویهای میگویند. ۳ـ I/O یا ورودی/خروجی: هدف وجود این توابع ارتباط با بخشهای مختلف سیستم است مانند: صفحهی نمایش، حافظهی سیستم، شبکه و ...
Mapping یا نگاشت کردن
توابع Pure بصورت کامل در رابطه با Mapping است. توابعی که آرگمانهای ورودی را به مقادیر خروجی نگاشت میکنند به عبارتی به ازای هر مجموعه از ورودیها یک خروجی منحصربفرد وجود دارد.مفهوم referential transparency
در ریاضیات هم توابعی وجود دارد که بسیار مشابه توابع در جاوااسکریپت هستند، مانند تابع جبری زیر: که به این معناست تابعی با نام f تعریف کردیم که آرگمان به نام x را دریافت میکند و در ۲ ضرب میکند.برای استفاده از آن به راحتی میتوانیم یک مقدار برای x در نظر بگیریم. در جبر، عبارت بالا دقیقا برابر نوشتن مقدار 4 است، به عبارتی در هر جایی قابل جایگزین شدن با 4 است بطوریکه مشکلی در محاسبات ایجاد نمیکند. به این خاصیت referential transparency میگویند. حال بگذارید این مورد را در جاوااسکریپت بررسی کنیم و تابع جبری بالا را به تابع جاوااسکریپت تبدیل کنیم.
const double = x => x * 2;
console.log(double(2)); // 4
console.log(10); // 10
برای داشتن referential transparency باید از توابع Pure استفاده کرد.
توابع Pure یا Pure Functions
توابع Pure برای اهداف مختلفی ضروری هستن مثل برنامهنویسی فانکشنال، هم زمانی و پیادهسازی کامپوننتهای UX قابل اطمینان. استفاده از توابع Pure تا زمانیکه امکان پیادهسازی نیازمندیهای یک برنامه با آنها وجود دارد پیشنهاد میشود. توابع Pure ورودیهایی را دریافت کرده و بر پایه آن ورودیها خروجیهایی را بر میگردانند. آنها سادهترین قسمتهای سازندهی کدهای یک برنامهاند که قابل استفادهی مجدد هستند. احتمالا یکی از مهمترین اصول طراحی در علوم کامپیوتر KISS است که مخفف Keep It Simple, Stupid یا Keep It Stupid Simple (به این مسئله اشاره میکند که بیشتر سیستمها اگر ساده نگه داشته شوند بهترین عملکرد خود را خواهند داشت در برابر حالتی که پیچیده شوند.) و استفاده از توابع Pure میتواند بهترین راهی باشد تا نرم افزار ما از اصل Stupid Simple یا همان بصورت احمقانهای ساده پیروی کند. یک تابع Pure باسد دو شرط زیر را داشته باشد: ۱ـ deterministic باشد یعنی به ازای هر ورودی یکسان داده شده یک خروجی یکسان برگرداند.۲ـ side effects یا تاثیرات جانبی نداشته باشد.
۱_ deterministic (برای هر ورودی تنها یک خروجی قطعی وجود دارد)
برای مثال به متد double توجه کنید، شما میتوانید همیشه فراخوانی تابع double را با مقدار خروجی آن جایگزین کنید مثلا همیشه برابر مقدار 10 در برنامهی ما هست و فرقی نمیکند در کدام قسمت برنامه، چه زمانی ویا چند بار فراخوانی شود.
این مثال را در نظر بگیرید:
Math.random(); // 0.4011148700956255
Math.random(); // 0.8533405303023756
Math.random(); // 0.3550692005082965
function time(){
return new Date().toLocaleTimeString();
}
time(); // "5:15:45 PM"
تابع زیر را در نظر بگیرید:
const highpass = (cutoff, value) => value >= cutoff;
highpass(5, 5); // true
highpass(5, 5); // true
highpass(5, 5); // true
highpass(5, 123); // true
highpass(5, 6); // true
highpass(5, 18); // true
highpass(5, 1); // false
highpass(5, 3); // false
highpass(5, 4); // false
۲ـ No Side Effects (بدون اثرات جانبی)
یک تابع Pure اثرات جانبی ندارد یعنی هیچ تغییری در state خارجی ایجاد نمیکند. Side Effect به هر تغییر در برنامه خارج از تابع و مقدار بازگشتی آن میباشد که شامل موارد زیر است.- ایجاد تغییر در هر متغیر یا object عمومی یا global
- لاگ کردن در کنسول با استفاده از console.log
- نوشتن یا نمایش چیزی در صفحهی نمایش
- نوشتن اطلاعات در یک فایل
- ارسال اطلاعات از طریق شبکه
- اجرا کردن هر فرایند خارجی یا عملیات I/O
- فراخوانی هر تابع خارجی دارای Side Effects
بررسی چند مثال
با توجه به آنچه آموختیم میخواهیم بررسی کنیم که آیا توابع زیر Pure هستند یا خیر. مثال ۱let globalState = 0;
function f(x) {
++globalState;
return x;
}
function f() {
return Date.now();
}
function f(x) {
console.log(x);
return x;
}
فرض کنید تابع getUsernameById یک درخواست ساده get ارسال میکند و بدون هیچ تغییری در دیتابیس، اطلاعات کاربر را دریافت کرده و بر میگرداند.
function f(id) {
const username = API.getUsernameById(id);
return username;
}
