۲۶ - ۷محاسبه‌ی نااکید قابلیت‌هامون رو تغییر میده

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

Prelude> let myList = [1, 2, 3]
Prelude> tail myList
[2,3]

دلیل اینکه هم در زبان‌های اکید و هم در زبان‌ها نااکید کار می‌کنه اینه که چیزی غیرقابل محاسبه نداره. اما با توجه به اینکه ‏‎undefined‎‏ (یکی از نمونه‌های تهی) در صورت اجبار شدن، خطا میده:

Prelude> undefined
*** Exception: Prelude.undefined

یه تفاوت بین اکید بودن و نااکید بودن می‌بینیم. این کُد فقط در زبان‌های نااکید کار می‌کنه:

Prelude> let myList = [undefined, 2, 3]
Prelude> tail myList
[2,3]

به خاطر اون تهی، یه زبانِ اکید سرِ درست کردن ِ ‏‎myList‎‏ خطا می‌داد. دلیل‌ش اینه که زبان‌های اکید همه‌ی بیانیه‌ها رو به محض درست شدن محاسبه می‌کنن. همون لحظه‌ای که ‏‎[undefined,2,3]‎‏ تعریف میشد، ‏‎undefined‎‏ به عنوانِ یه آرگومان به ‏‎(:)‎‏ محاسبه میشد و یه استثنا می‌داد. در مقابل تو هسکل، محاسبه‌ی نااکید باعث میشد اون مقدارِ تهی تا زمانی که لازم نشده محاسبه نشه.

ببینین آیا می‌تونین (با دلیل) تشخیص بدین که این مثال استثنا میده یا نه؟

Prelude> head $ sort [1, 2, 3, undefined]

وقتی ‏‎head‎‏ رو به یه تابع که به ‏‎sort‎‏ داده شده اعمال می‌کنیم، فقط کوچکترین مقدارِ لیست رو لازم داریم، و کل کاری که انجام میشه همینه. مشکل اینجاست که ‏‎sort‎‏ برای پیدا کردنِ کمترین مقدار باید ‏‎undefined‎‏ رو حساب کنه، که اون هم خطا میده.