۳ - ۴تعاریف سطح بالا و محلی

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

متضادِ تعاریف سطح بالا، تعاریفِ محلی هستن. چیزی که محلی تعریف شده، یعنی زیر یه بیانیه‌ی دیگه تودرتو شده، و خارج از اون بیانیه قابل دسترسی نیست. در فصلِ قبلی، چند بار با ‏‎let‎‏ و ‏‎where‎‏ مقادیرِ محلی تعریف کردیم. با مثال زیر دوره می‌کنیم:

module TopOrLocal where

topLevelFunction :: Integer -> Integer
topLevelFunction x =
  x + woot + topLevelValue
  where woot :: Integer
        woot = 10

topLevelValue :: Integer
topLevelValue = 5

اگه از یه ماژول ِ دیگه، ماژول ِ بالا (‏‎TopOrLocal‎‏) رو وارد کنین، به ‏‎topLevelFunction‎‏ و ‏‎topLevelValue‎‏ دسترسی پیدا می‌کنین. ولی ‏‎woot‎‏، خارج از ‏‎topLevelFunction‎‏ عملاً نامرئی‌ه. در هسکل، عباراتِ ‏‎let‎‏ و ‏‎where‎‏ برای انقیاد یا تعریف‌های محلی به کار میرن. منظور از انقیاد کردن یا تعریف کردن، دادنِ اسم به یه بیانیه‌ست. میشه توابع رو بی‌نام تعریف کرد و هر دفعه تابع رو تماماً نوشت، اما با نامگذاری و استفاده از اسم‌ِش (بجای کلِ تابع) تکرار کمتر میشه.

نکته‌ی دیگه اینکه ما برای ‏‎woot‎‏ هم، تایپِ‌ش رو با گرامر ِ ‏‎::‎‏ زیرِ ‏‎where‎‏ صراحتاً نوشتیم. این کار اصلاً لازم نبود (استنتاجِ تایپ ِ هسکل خودش تشخیص میداد)، اما اینجا نوشتیم تا گرامر ِ تایپ سیگنچرِ محلی رو هم دیده باشین. حتماً این کد رو تو REPL بارگذاری و اجرا کنین:

Prelude> :l TopOrLocal.hs
[1 of 1] Compling TopOrLocal
Ok, modules loaded: TopOrLocal.
*TopOrLocal> topLevelFunction 5
20

با آرگومان‌های دیگه هم امتحان کنین، خودتون هم توی ذهن (یا روی کاغذ) مراحل محاسبات رو انجام بدین تا از درک نتایج حاصل مطمئن بشین.

تمرین‌ها: گستره

۱.

این کُدها در یک جلسه توی REPL نوشته شدن. آیا ‏‎y‎‏ در گستره ِ ‏‎z‎‏ هست؟

Prelude> let x = 5
Prelude> let y = 7
Prelude> let z = x * y

۲.

این کُدها در یک جلسه توی REPL نوشته شدن. آیا ‏‎h‎‏ در گستره ِ ‏‎g‎‏ هست؟

Prelude> let f = 3
Prelude> let g = 6 * f + h

۳.

این نمونه کد از یه فایلِ منبع ِه. آیا برای اجرای ‏‎area‎‏، هر چیزی که لازم داریم در گستره هست؟

area d = pi * (r * r)
r = d / 2

۴.

این کد هم از یه فایل منبع ِه. آیا ‏‎r‎‏ و ‏‎d‎‏ در گستره ِ ‏‎area‎‏ هستن؟

area d = pi * (r * r)
   where r = d / 2