مسئله فانارگ

**مسئله فانارگ **

کلمه **فانارگ**  کوتاه شده عبارت Functional Argument می‌باشد. در علوم کامپیوتر مسئلهٔ فانارگ به پیچیدگی نحوهٔ پیاده‌سازی توابع کلاس اول توسط زبان‌های برنامه‌سازی اشاره دارد. در واقع در این توابع از یک حافظهٔ پشته ای برای پیاده‌سازی توابع استفاده می‌شود.
در واقع پیچیدگی مسئلهٔ فانارگ زمانی رخ می‌دهد که بدنهٔ یک تابع تودرتو به صورت مستقیم به شناسه‌های توابع تعریفی اشاره کند. برای برطرف کردن این پیچیدگی توسط زبان‌های برنامه‌نویسی دو راهکار وجود دارد که عبارتند از: حذف این نوع ارجاع و استفاده از تابع‌هایی تحت عنوان بستار .

دو گونهٔ مختلف از مسئلهٔ فانارگ عبارتند از: مسئلهٔ فانارگ رو به بالا  و مسئلهٔ فانارگ رو به پایین .

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

### راه حل‌های مسئلهٔ فانارگ رو به بالا
* راه حل اول: استفاده از داده ساختار هرم به جای پشته
در صورت استفاده از داده ساختار هرمی می‌توان از امکانات زباله روبی (Garbage Collection) و مرجع شماری (Reference Counting) بهره برد. با این کار هر زمان که داده‌های داخل پشته مورد استفاده قرار نگیرند توسط این امکانات حذف می‌شوند. از معایب این روش این می‌باشد که با توجه به سرعت پایینتر هرم، کارایی برنامه با نرخ بسیار زیادی کاهش می‌یابد.
* راه حل دوم: کامپایلر ترکیبی (Hybrid)
راه حل دوم استفاده از کامپایلرهای ترکیبی می‌باشد که می‌توانند از بین پشته و هرم بهترین داده ساختار را برای ذخیره داده‌های تابع انتخاب نمایند.
* راه حل سوم: انتقال متغیرها به داخل بستار
راه حل دیگری که می‌توان از آن استفاده کرد انتقال دادن متغیرها به داخل تابع بستار در زمان تعریف آن می‌باشد. بهترین کارایی این روش زمانی است که بدانیم متغیرهای تابع همواره مقداری ثابت را دارند. زیرا با این روش نمی‌توان مقدار یک متغیر را بین توابع به اشتراک گذاشت. برخی از زبان‌های برنامه‌نویسی مانند PHP این امکان را می‌دهند که برنامه‌نویس به صورت مستقیم متغیرهای بستار را با توابعی مانند`()use` تعیین کند.

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

## کاربردهای عملی
با بررسی زبان‌های برنامه‌نویسی مختلف می‌توان فهمید که همواره پیاده‌سازی فانارگ رو به بالا دشوارتر از فانارگ رو به پایین بوده‌است. در ادامه به بررسی برخی از زبان‌های برنامه‌نویسی در این زمینه می‌پردازیم:
* زبان برنامه‌نویسی پاسکال: در زبان پاسکال این امکان وجود دارد که یک تابع به عنوان آرگمان ورودی به تابع دیگر داده شود اما امکان بازگرداندن تابع توسط تابع دیگر وجود ندارد. این یعنی برای پیاده‌سازی زبان پاسکال نیاز به برطرف کردن فانارگ رو به بالا وجود ندارد و تنها باید فانارگ رو به پایین پیاده شود.
* زبان برنامه‌نویسی اوبرون: در این زبان برنامه‌نویسی هر دو امکان ارجاع تابع و بازگرداندن تابع وجود دارد اما این توابع نمی‌توانند توابعی تودرتو باشند.
* زبان برنامه‌نویسی سی: در زبان برنامه‌نویسی سی از رخداد مسئلهٔ فانارگ به کلی جلوگیری شده‌است. کمپانی اپل یک ساختار نحوی‌ای برای زبان سی ارائه کرده‌است که از طریق انتقال خودکار بستار از داده‌ساختار پشته‌ای به هرمی، بتواند مسئلهٔ فانارگ رو به بالا را پشتیبانی کند.
* زبان برنامه‌نویسی جاوا:در زبان برنامه‌نویسی جاوا با استفاده از کلیدواژه Final در Inner Class این مفهوم پشتیبانی شده‌است.
* زبان‌های برنامه‌نویسی سی‌شارپ و دی: در این زبان‌های برنامه‌نویسی از لامبدا(Lambda) برای پیاده‌سازی بستارها استفاده می‌کنند.

## جستارهای وابسته
* *[[علوم کامپیوتر]]*
* *[[زبان‌های برنامه‌سازی]]*
* *[[پشته]]*
* *[[بستار]]*
* *[[هرم (علوم رایانه)]]*
* *[[زباله روب (علوم رایانه)]]*
* *[[مرجع شماری]]*

## منابع
* ویکی‌پدیای انگلیسی

رده:کامپایلرسازی