برای تعریف یک تابع سراسری در Common Lisp از عبارت defun استفاده میشود.
این عبارت به عنوان اولین آرگومانش فهرستی از پارامترها میگیرد (فهرست خالی یعنی تابع هیچ پارامتری ندارد).
پس از آن یک رشتهی مستندات اختیاری میآید (به پایین نگاه کنید) و سپس صفر یا چند عبارت که «بدنهی» تابع را تشکیل میدهند.
توابع میتوانند صفر یا چند پارامتر داشته باشند.
(defun no-args () (+ 1 1))
(defun add-one (x) (1+ x))
(defun add-nums (x y) (+ x y))
برای فراخوانی یک تابع، عبارتی ارزیابی میشود که نماد معرف تابع، اولین عنصر آن است و آرگومانهای تابع (در صورت وجود) عناصر باقیماندهی آن عبارتاند.
مقداری که یک تابع به آن ارزیابی میشود، مقدار آخرین عبارتی است که در بدنهی تابع ارزیابی شده است. همهی توابع به یک مقدار ارزیابی میشوند.
(add-nums 2 2) ;; => 4
توابع میتوانند بهصورت اختیاری یک رشتهی مستندات هم داشته باشند (که به آن «داکاسترینگ» هم میگویند).
اگر ارائه شود، بعد از فهرست آرگومانها اما پیش از بدنهی تابع میآید.
میتوان با documentation به رشتهی مستندات دسترسی داشت.
(defun add-nums (x y) "Add X and Y together" (+ x y))
(documentation 'add-nums 'function) ;; => "Add X and Y together"
;; Note that if one provides a docstring but fails to provide a body
;; then the docstring is interpreted by Common Lisp as the body, not
;; the docstring
(defun no-body ())
(no-body) ;; => NIL
(defun mistake () "This is not a docstring")
(mistake) ;; => "This is not a docstring"
(documentation 'mistake 'function) ;; => NIL
لیلی، فضاییِ Lisp، برگشته است و دارد بیشتر آشپزی میکند! این بار میخواهد لازانیای فضایی Lisp را درست کند که کاملاً هم بیشباهت به لازانیای انسانها نیست.
لیلی به چند تابع نیاز دارد که نوشته شوند تا به مشخص کردن زمان پخت لازانیا کمک کنند. و هر کدام باید مستندات خوبی داشته باشند تا لیلی فراموش نکند هر کدام چه کاری انجام میدهند.
میتوانید به لیلی کمک کنید توابعی بنویسد که به او در زمانبندی پخت لازانیا کمک کنند؟
تابع expected-time-in-oven را تعریف کنید که هیچ پارامتری نمیگیرد و برمیگرداند که لازانیا باید چند دقیقه در فر بماند. طبق سنت فضاییهای Lisp (دقیقاً همانطور که واحد والدینی لیلی آشپزی میکرد)، زمان مورد انتظار در فر بر حسب دقیقه 337 است:
(expected-time-in-oven) ;; => 337
تابع remaining-minutes-in-oven را تعریف کنید که تعداد دقیقههایی را که لازانیا تاکنون در فر بوده است به عنوان پارامتر میگیرد و بر اساس زمان مورد انتظار در فر بر حسب دقیقه از کار قبلی، برمیگرداند که لازانیا باید چند دقیقهی دیگر در فر بماند.
(remaining-minutes-in-oven 100) ;; => 237
تابع preparation-time-in-minutes را تعریف کنید که تعداد لایههایی را که لیلی به لازانیا اضافه کرده است به عنوان پارامتر میگیرد و برمیگرداند که لیلی چند دقیقه صرف آمادهسازی لازانیا کرده است، با این فرض که آمادهسازی هر لایه 19 دقیقه طول میکشد.
(preparation-time-in-minutes 3) ;; => 57
تابع elapsed-time-in-minutes را تعریف کنید که دو پارامتر میگیرد: پارامتر اول تعداد لایههایی است که لیلی به لازانیا اضافه کرده است و پارامتر دوم تعداد دقیقههایی است که لازانیا در فر بوده است. تابع باید برمیگرداند که لیلی چند دقیقه روی پخت لازانیا کار کرده است، که برابر است با مجموع زمان آمادهسازی بر حسب دقیقه و زمانی که لازانیا تا این لحظه در فر گذرانده است.
(elapsed-time-in-minutes 3 100) ;; => 157
در Exercism ثبتنام کنید تا Common Lisp را همراه با 27 مفهوم92 تمرین و مربیگری انسانی واقعی یاد بگیرید و در آن استاد شوید، همهی اینها رایگان.