۲۶ - ۷محاسبهی نااکید قابلیتهامون رو تغییر میده
بعداً با جزئیات بیشتر، ترتیبِ معمولیِ محاسبه (استراتژیِ نااکید که هسکل برای پیادهسازیهاش پیشنهاد کرده) رو توضیح میدیم. الان به چندتا مثال از قابلیتهایی که نااکید بودن میده نگاه میکنیم. این کد با هردو استراتژیِ محاسبه ِ اکید یا نااکید کار میکنه:
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
رو حساب کنه، که اون هم خطا میده.