سعید نوری
سعید نوری
خواندن ۸ دقیقه·۷ سال پیش

پس شما می‌خواهید یک برنامه‌نویس تابع‌گرا (فانکشنال) شوید؟(قسمت ششم)

اولین قدم‌ها برای یادگیری برنامه‌نویسی فانکشنال مهم‌ترین قدم‌ها هستند و در برخی اوقات سخت‌ترین قدم‌ها. البته اگر از راه درست وارد شوید چندان هم سخت نخواهد بود.


خب حالا چه؟

حالا که شما همه‌ی این چیزهای جالب جدید را آموختید ممکن است بپرسید: خب حالا چه؟ چگونه از این چیزهای جدید در برنامه‌نویسی هر روزه‌ام استفاده کنم؟

خوب این بستگی دارد. اگر شما می‌توانید با یک زبان تابع‌گرای خالص مثل Elm یا Haskell کد بزنید شما می توانید همه‌ی این ایده‌ها را به کار بگیرید. این نوع زبان‌ها انجام این کار را تسهیل می‌کنند.

اگر شما فقط می‌توانید با یک زبان‌ امری مانند جاوا اسکریپت کد بزنید، همچنان که همه‌ی ما مجبوریم، شما همچنان می‌توانید از خیلی از مفاهیمی که اینجا آموخته‌اید استفاده کنید، هر چند که برای این کار باید انضباط کاری زیادی به خرج دهید.


جاوا اسکریپت تابع‌گرا

جاوا اسکریپت ویژگی‌های زیادی دارد که به شما اجازه می‌دهد به شکل تابع‌گرا کد بزنید. جاوا اسکریپت یک زبان تابع‌گرای خالص نیست اما شما می‌توانید با آن به مقداری از تغییرناپذیری (Immutability) دست پیدا کنید، و حتی با بعضی از کتابخانه‌ها‌ی آن به مقدار بیشتری برسید.

البته این ایده‌آل نیست اما اگر شما مجبور به استفاده از آن هستید چرا از بعضی از ویژگی‌های تابع‌گرای آن استفاده نکنید؟

تغییرناپذیری

اولین چیزی که باید به آن رسیدگی شود تغییرناپذیری است. در استاندارد ES2015 یا ES6 یک کلمه کلیدی جدید به نام const وجود دارد. هر گاه یک متغیر با این کلمه تعریف شود، آن متغیر بعد از گرفتن مقدار دیگر مقدارش تغییر نخواهد کرد:

const a = 1; a = 2; // this will throw a TypeError in Chrome, Firefox or Node // but not in Safari (circa 10/2016)

در کد بالا a به عنوان یک ثابت تعریف شده است و مقدار ۱ را گرفته است. به همین دلیل وقتی مفسر جاوا اسکریپت به a=2 می‌رسد یک استثنا تولید می‌کند (البته به جز مفسر مرورگر Safari)

مشکلی که const در جاوا اسکریپت دارد این است که چندان هم سختگیر نیست. مثال زیر به روشن شدن موضوع کمک می‌کند:

const a = { x: 1, y: 2 }; a.x = 2; // NO EXCEPTION! a = {}; // this will throw a TypeError

دقت کنید که چگونه عبارت a.x=2 هیچگونه استثنایی را تولید نکرده است. تنها چیزی که با کلمه کلیدی const تغییرناپذیر شده است متغیر a است. هر چیزی که a به آن اشاره کن می‌تواند تغییر کند.

این واقعا ناامید کننده است زیرا جاوا اسکریپت با آن می‌توانست خیلی بهتر شود.پس ما چگونه در جاوا اسکریپت به تغییرناپذیری برسیم؟

متاسفانه ما فقط با یک کتابخانه جاوا اسکریپت به نام Immutable.js این کار را انجام دهیم. این کتابخانه هر چند که می‌تواند ما را به تغییرناپذیری بیشتری برساند اما متاسفانه باعث می شود کدمان بیشتر شبیه جاوا شود تا جاوا اسکریپت.

کاری کردن و ترکیب (Currying and Composition)

قبلا در این سری از آموزش‌ها ما یاد گرفتیم که چگونه توابع را به صورت کاری شده بنویسیم. در زیر یک مثال پیچیده‌تر می‌بینید:

const f = a => b => c => d => a + b + c + d

توجه کنید که در جاوا اسکریپت ما مجبوریم قسمت کاری کردن را خودمان بنویسیم. و صدا زدن تابع f را باید اینجوری انجام دهیم:

console.log(f(1)(2)(3)(4)); // prints 10

کد بالا آنقدر پرانتز دارد که یک برنامه‌نویس زبان لیسپ را به گریه می‌اندازد! کتابخانه‌های زیادی هستند که این پروسه را راحت‌تر می‌کنند، کتابخانه مورد علاقه من Ramda نام دارد.

با استفاده از Ramda حالا ما می‌توانیم بنویسیم:

const f = R.curry((a, b, c, d) => a + b + c + d); console.log(f(1, 2, 3, 4)); // prints 10 console.log(f(1, 2)(3, 4)); // also prints 10 console.log(f(1)(2)(3, 4)); // also prints 10

تعریف تابع چندان بهتر نشده است اما ما نیاز به استفاده از آن همه پرانتز را حذف کرده‌ایم. دقت کنید که ما می توانیم تعداد پرانتزها را هنگام فراخوانی تابع f کم و زیاد کنیم.

با استفاده از کتابخانه Ramda ما می‌توانیم تابع mult5AfterAdd10 موجود در قسمت‌های سوم و چهارم از این سری آموزش‌ها را بازنویسی کنیم:

const add = R.curry((x, y) => x + y); const mult5 = value => value * 5; const mult5AfterAdd10 = R.compose(mult5, add(10));

کتابخانه Ramda دارای تعداد زیادی تابع کمکی مانند R.add و R.multiply است که به ما کمک می‌کنند کد کمتری بنویسیم:

const mult5AfterAdd10 = R.compose(R.multiply(5), R.add(10));


توابع نگاشت، فیلتر و کاهش (Map, Filter and Reduce)

کتابخانه Ramda همچنین دارای توابع map,filter و reduce مخصوص به خود است. هر چند که این توابع در Array.prototype در خود جاوا اسکریپت هم وجود دارند ولی نسخه Ramdaی این توابع کاری شده هستند. به مثال زیر توجه کنید:

const isOdd = R.flip(R.modulo)(2); const onlyOdd = R.filter(isOdd); const isEven = R.complement(isOdd); const onlyEven = R.filter(isEven); const numbers = [1, 2, 3, 4, 5, 6, 7, 8]; console.log(onlyEven(numbers)); // prints [2, 4, 6, 8] console.log(onlyOdd(numbers)); // prints [1, 3, 5, 7]

تابع R.modulo دو تا پارامتر می‌گیرد: پارامتر اول مقسوم (چیزی که قرار است تقسیم شود) و پارامتر دوم مقسوم علیه (چیزی که تقسیم بر آن را انجام می‌دهیم).

تابع isOdd باقیمانده تقسیم بر ۲ است، اگر باقیمانده صفر شود عدد فرد نیست و اگر باقیمانده ۱ شود عدد فرد است. ما پارامتر های تابع modulo را برعکس (flip) کرده‌ایم در نتیجه می‌توانیم از عدد ۲ به عنوان پارامتر اول این تابع استفاده کنیم.

تابع isEven مکمل[ریاضی] تابع isOdd است.

تابع onlyOdd یک تابع فیلتر است که تابع تطابق آن(تابعی که مقدار بولین برمی‌گرداند) تابع isOdd است. تابع isOdd قبل از اجرا منتظر گرفتن لیستی از اعداد به عنوان آخرین پارامترش می‌ماند.

تابع onlyEven یک تابع فیلتر است که از تابع isEven به عنوان تابع تطابقش استفاده می‌کند. وقتی ما لیست numbers را به توابع onlyEven و onlyOdd پاس می‌دهیم توابع isOdd و isEven آخرین پارامترشان را می‌گیرند و اجرا می‌شوند و اعدادی که ما می‌خواهیم را برگشت می‌دهند.


نقایص جاوا اسکریپت

با تمام کتابخانه‌ها و بهبود داخلی که جاوا اسکریپت تا حالا داشته باز هم از این حقیقت رنج می‌برد که یک زبان امری است که سعی می‌کند همه چیز را برای همه کس فراهم کند.

اغلب برنامه‌نویسان فرانت‌اند سال‌هاست که به جاوا اسکریپت برای توسعه برنامه‌هایشان در مرورگرها چسبیده‌اند زیرا دیر زمانی ست که این تنها انتخاب‌شان بوده. اما امروزه خیلی‌ از توسعه دهندگان نوشتن جاوا اسکریپت را به صورت مستقیم کنار گذاشته‌اند. به جای آن این برنامه‌نویسان از زبان‌هایی استفاده می‌کنند که به جاوا اسکریپت کامپایل می‌شوند، یا به عبارت صحیح‌تر منتقل (transpiling) می‌شوند.

کافی‌اسکریپت یکی از نخستین زبان‌هایی بود که از این مکانیسم استفاده می‌کرد. و امروزه تایپ‌اسکرپت به وسیله انگولار۲ پذیرفته شده است ( زبان پیش‌فرض در توسعه انگولار۲ تایپ‌اسکریپت است). همچنین کتابخانه Babel هم می‌تواند به عنوان یک مبدل جاوا اسکریپت در نظر گرفته شود. هر روز تعدا بیشتری از برنامه‌نویسان در مورد این روش برای توسعه کد صحبت می‌کنند. اما همه‌ی این زبان‌ها با جاوا اسکریپت شروع شده‌اند و آن را قدری بهتر می‌کنند. چرا راه را کامل نرویم و از یک زبان تابع‌گرای خالص برای انتقال به جاوا اسکریپت استفاده نکنیم؟


زبان Elm

در این سری از مقالات ما به زبان Elm برای فهم بهتر برنامه‌نویسی تابع‌گرا نگاهی انداختیم. اما زبان Elm چیست؟ و چگونه می‌توانیم از آن استفاده کنیم؟

زبان Elm یک زبان تابع‌گرای خالص است که به جاوا اسکریپت کامپایل می‌شود، در نتیجه شما می‌توانید از آن برای توسعه برنامه‌های تحت وب با کمک گرفتن از The Elm Architecture استفاده کنید.

برنامه‌هایی که با Elm نوشته شده‌اند هیچگونه خطای زمان اجرایی تولید نمی‌کنند.

زبان Elm در شرکت‌هایی مثل NoRedInk استفاده می شود. این شرکت خالق این زبان جناب Evan Czapliki را استخدام کرده‌ است.

برای اطلاعات بیشتر نگاهی به این سخنرانی بیندازید.

ممکن است بپرسید: آیا من مجبورم که تمام کد‌های جاوا اسکریپتم را با Elm جایگزین کنم؟نه، شما می‌توانید به صورت افزایشی بعضی از قسمت‌ها را جایگزین کنید، برای اطلاعات بیشتر نگاهی به این مقاله بیندازید.

چرا زبان Elm را یادبگیریم؟

۱. کد زدن با یک زبان تابع‌گرای خالص هم مزایایی دارد و هم مشکلاتی. آنچه می‌توانید با این زبان‌ انجام دهید محدود است ولی در عین حال شما را از باگ‌ها و طراحی بد خلاص می‌کند زیرا همه‌ی برنامه‌های نوشته شده با این زبان از الگوی Elm Architecture پیروی می‌کنند که یک مدل تابع‌گرای واکنشی است.

۲. برنامه‌نویسی تابع‌گرا شما را تبدیل به برنامه‌نویس بهتری می‌کند. ایده‌هایی که در این مجموعه مقالات گفته شد تنها نوک کوه یخ است، شما باید آنها را در عمل ببینید تا بفهمید که چگونه آنها برنامه شما را کم‌حجم‌تر و پایدارتر می‌کنند.

۳. جاوا اسکریپت در ۱۰ روز ساخته شد سپس در دو دهه اخیر به آن وصله اضافه شدن تا قدری تابع‌گرا باشد، قدری شی‌گرا و به طور کامل امری.

زبان Elm با استفاده از تجربه کاری جامعه کاربری Haskell در ۳۰ سال گذشته طراحی شده است که تجربه چند دهه کار با ریاضیات و علوم کامپیوتر را دارند.

الگوی (The Elm Architecture (TEA به مدت چند سال طراحی و بهبود داده شده است که حاصل نظریه خالق زبان Elm در برنامه‌نویسی تابع‌گرای واکنشی است. برای درک سطح تفکری که پشت فرموله‌سازی این الگو وجود دارد این ویدئو را ببینید.

۴. زبان Elm برای توسعه فرانت‌اند وب طراحی شده است. هدف این زبان این است که کار توسعه‌دهندگان فرانت‌اند را راحت‌تر کند. برای درک بهتر این هدف این ویدئو را ببینید.


آینده

ممکن نیست که بفهمیم که در آینده چه اتفاقی خواهد افتاد، اما می‌توانیم حدس‌هایی بزنیم. در زیر چند مورد از آنها را می‌بینید:

۱. در آینده گرایش واضحی به سمت زبان‌هایی که به جاوا اسکریپت کامپایل می‌شوند وجود خواهد داشت.

۲. ایده‌هایی از برنامه‌نویسی تابع‌گرا که به مدت ۴۰ سال وجود داشته‌اند به منظور حل پیچیدگی‌های فعلی برنامه‌نویسی دوباره کشف می‌شوند.

۳. دوران شکوه سخت‌افزار ( گیگ‌ها بایت‌ از حافظه ارزان قیمت و پردازنده‌های پر سرعت) باعث می شود که تکنیک‌های تابع‌گرا ماندنی شوند.

۳. پردازنده‌ها سریع تر نمی‌شوند بلکه تعداد هسته‌های آنها افزایش پیدا می‌کند.

۴. حالت تغییرپذیر (Mutable state) به عنوان یکی از بزرگترین مشکلات سیستم‌های پیچیده شناخته خواهد شد.

من این سری از مقالات را نوشتم چون باور دارم که برنامه‌نویسی تابع‌گرا آینده‌ی برنامه‌نویسی خواهد بود و همچنین به خاطر اینکه در دو سال گذشته با این مدل برنامه‌نویسی برای یادگیری آن سر و کله زده‌ام (من هنوز در حال یادگیری هستم).

هدف من این بود که به دیگران کمک کنم که این مفاهیم را سریع‌تر و آسان‌تر از من یاد بگیرند. و اینکه کمک کنم دیگران تبدیل به برنامه‌نویس بهتری شوند تا بازارکار بهتری در آینده داشته باشند.

حتی اگر پیش‌بینی من مبنی بر اینکه زبان Elm یکی از مهم‌ترین زبان‌ها در آیند خواهد بود اشتباه باشد، من با اطمینان می‌توانم بگویم که برنامه نویسی‌ تابع‌گرا و Elm جزو چیز‌هایی هستند که در آینده‌ی برنامه‌نویسی وجود دارند.

امیدوارم که بعد خواندن این سری مقالات اعتماد به نفس شما افزایش پیدا کرده باشد و درک شما از این مفاهیم بالاتر رفته باشد.

برایتان آرزوی موفقیت می‌کنم.


ادامه ندارد!

لینک قسمت‌های اول،دوم،سوم،چهارم و پنجم: +و+و+و+و+

لینک منبع: +



برنامه‌نویسی تابع‌گرابرنامه‌نویسی فانکشنالبرنامه‌نویسی تابعیتابع‌گرافانکشنال
علاقه‌مند به فناوری، توسعه دهنده پایتون و بک‌اند در آینده‌ای دور یا نزدیک!
شاید از این پست‌ها خوشتان بیاید