برنامه نویسی فانکشنال : معرفی

این قسمت، شامل دنباله‌ای از مقاله‌هاست که قصد اش تشریح مدل برنامه نویسی فانکشنال است؛ اگر فکر می‌کنید که به قدر کافی با مدل فانکشنال آشنایی دارید، می‌توانید مستقیما به قسمت رهنمای شروع الیکسیر مراجعه نمایید.

برای درک بهتر هر کدام از این بخش‌ها، باید ابتدا بخش‌های قبلی آن را مطالعه کرده باشید. بنابراین نوشته‌های این قسمت را به همین ترتیبی که در زیر آمده است مطالعه نمایید:

زبان‌های فانکشنال تا الان کجا بوده‌اند؟

برنامه نویسی فانکشنال، تابعی، تابع گرا، و یا هر طوری که شما صدایش می‌زنید، چند سالی است که بسیار محبوب شده است. شاید خیلی‌ها ندانند، اما برنامه نویسی فانکشنال چیز جدیدی نیست و اتفاقا از پارادایم‌های قدیمی برنامه‌ نویسی است! بسیاری از ایده‌های فانکشنال سال‌ها پیش با ظهور زبان Lisp به دنیای برنامه نویسی وارد شدند؛ اما این زبان‌ها تا الآن کجا بودند؟ اگر قدمتی طولانی دارند، چرا بعد از این همه سال تازه به محبوبیت رسیده‌اند؟

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

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

چرا محبوبیت پیدا کردند؟

یک روز ورق برگشت! داستان معروفی که همه‌مان شنیده ایم: تولید کنندگان سخت افزار به این نتیجه رسیدند که بالابردن سرعت یک پردازشگر (میزان گیگاهرتز)، دیگر توجیه عملی ندارد؛ و در حال حاضر مناسب ترین راه حل این است که به جای داشتن «یک» پردازنده‌ی خیلی سریع، بهتر است از «چند» پردازنده با سرعت متعادل استفاده کنند.

بنابراین روند ساخت پردازنده‌ها از این روش:

  • ساخت پردازنده‌ای که یک هسته‌ی پردازشی خیلی سریع دارد.

به این روش تغییر کرد:

  • ساخت پردازنده‌ای با چندین هسته‌ی پردازشی، با سرعتی متعادل!
  • افزایش تعداد هسته‌ها، به جای افزایش سرعت پردازنده.
  • افزایش سرعت و حجم حافظه‌ی کش.
  • تمرکز روی بهینه سازی سرعت رد و بدل شدن اطلاعات بین هسته‌ها.
  • بهینه سازی دسترسی پردازشگر به دیگر عناصر سیستم (قرار دادن عناصر سخت افرای بیشتر به همراه هسته‌ها در هر چیپ)

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

  • ۱. تا پیش از این الگوریتم‌ها حالتی ترتیبی و سریالی داشتند. حالا باید الگوریتم‌ها را طوری طراحی کنیم که قابلیت تقسیم شدن به واحدهای کوچک‌تر را داشته باشند. (پر رنگ شدن الگوی معروف «تقسیم و غلبه»)

  • ۲. تا پیش از این داده‌هایی که الگوریتم‌ها روی آ‌ن کار می‌کردند حالتی متمرکز داشتند. حالا باید داده‌ها را به طور غیر متمرکز سازماندهی کنیم تا قابل پخش شدن باشند.

یک مثال کاملا تئوری: اگر قبلا یک حلقه داشتیم که روی آرایه‌ای ۲۰۰۰ عنصری کار می‌کرد، حالا باید چهار حلقه داشته باشیم که هر کدام روی آرایه‌های ۵۰۰ عنصری کار کنند! به این ترتیب هم الگوریتم را به قسمت‌های کوچک‌تر تقسیم کرده ایم و هم داده‌های مورد نیاز الگوریتم را از حالت متمرکز خارج کردیم تا بتوانیم عناصر را بین حلقه‌ها پخش کنیم.

  • ۳. تا پیش از این اعمال همروند و موازی جزو کارهایی بود که به ندرت مورد استفاده قرار می‌گرفت، اما حالا به مبحثی مهم و حیاتی تبدیل شده است، پس باید از ابزارهایی استفاده کنیم که برای اعمال همروند و موازی بهینه باشند.

طولی نکشید که برنامه‌نویسان دریافت‌اند زبان‌های دستوری محبوب‌شان، خیلی برای این مدل جدید کدنویسی مناسب نیستند. در جستجو برای یافتن ابزاری مناسب، نظر همه به سمت زبان‌های فانکشنال جلب شد، زبان‌هایی که خصوصیات‌شان آن‌ها را برای چنین موضوعی بسیار کارآمد می‌کرد. مسلما توسعه‌ی برنامه‌های همروند و موازی تنها نقطه‌ی قوت این زبان‌ها نیست؛ بنابراین برنامه نویسانی که هدف اصلی‌شان از رو آوردن به این زبان‌ها چنین چیزی بوده، متوجه شدند که این زبان‌ها جدای از کارآمد بودن در این زمینه‌ی خاص، دارای ویژگی‌های بسیار مفید دیگری هم هستند که آن‌ها از آن بی خبر بودند! تمام این‌ها باعث شد امروز که شما در حال خواندن این مطلب هستید، استفاده از زبان‌های فانکشنال به امری عادی و همه‌گیر تبدیل شود.

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

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

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