8
در اينجا آرگومانها 5, 7, (min 9 8), 4 هستند كه در اولويتي قبل از تابعي به نام max كه نتيجه مقادير آرگومانها را به كار ميبرد ارزيابي ميشوند. آرگومان اول 4 ، يك عدد است پس مقدار آن 4 است. آرگومان دوم (min 9 8) است كه خودش يك فراخواني تابع است. بنابراين بايد قبل از آرگومان سوم فراخواني شود، (min 9 8) بايد توسط مفسر Lisp ارزيابي شود. چون ما بايد مفسر Lispرا براي بعضي آرگومانها در طول ارزيابي همه فراخوانيهاي توابع استفاده كنيم ميتوان گفت مفسر Lisp بصورت بازگشتي فراخواني شده است. مفسر Lisp همان مراحل را به كار ميبرد، پس آرگومان اول 9 قبل از آرگومان دوم 8، ارزيابي ميشود. با بكار برروي تابع min حاصل 8 ميشود يعني تابع كوچكترين عدد يك مجموعه از اعداد صحيح را محاسبه ميكند. براي تابع بيروني max هم به اين معني است كه آرگومان دوم آن 8 ارزيابي ميشود.
آرگومانهاي بعدي 7و5هستند كه نتيجه ارزيابي آنها مقادير 7و5 ميشود. حال تابع بزرگترين عدد كه max نام دارد ميتواند ارزيابي شود كه 8 برميگرداند. اين مقدار نهايي، مقدار فراخواني همه توابع ميباشد. از آنجايي كه گفته ميشود مفسر Lisp هميشه سعي ميكند مقدار يك نماد يا تفسير يك ليست بعنوان يك فراخواني تابع را تشخيص دهد ما چگونه ميتوانيم با نمادها و ليستها بعنوان داده رفتار كنيم؟ براي مثال، اگر ما ليست (peter walks home) را وارد كنيم، آنگاه مفسر Lisp فوراً يك خطا ميدهد كه چيزي شبيه اين خطا ميگويد: تابع peter ناشناخته است (مفسرLisp بايد بقدري باهوش باشد كه بتواند ابتدا كنترل كند كه آيا تعريف تابعي براي نام تابع تعيين شده وجود دارد يا نه، قبل از اينكه هر آرماگوني را ارزيابي كند). يا اگر ما فقط house را وارد كنيم، آنگاه مفسر Lisp با خطايي شبيه اين خطا خاتمه مييابد: مقداري به house متصل نيست (تخصيص نيافته است). حل اين مسئله كاملاً آسان است. زيرا عنصر اصلي هر ليست بعنوان نام تابع تفسير ميشود،هر سيستم Lisp با يك تابع پيشساخته quote ميآيد كه يك عبارت نمادين را بعنوان آرگومان پذيرفته و اين عبارت نمادين را بدون ارزيابي آن برميگرداند. براي مثال: ليست(quote(peter walks home)) ، به سادگي مقدار
(peter walks home) را برميگرداند، و براي (quote house)، آن house را بر ميگرداند. از آنجايي كه تابع quote زياد استفاده ميشود، ميتوان آن را با كاراكتر ويژه ' بيان كرد. بنابراين براي مثال بالا ميتوانيم معادل’(Peter walks home) و’house را مشخص كنيم. برنامهها بعنوان داده، يعني تابع quote به ما امكان ميدهد تا با فراخواني تابع بعنوان داده رفتار كنيم. براي مثال: (quote (max 4 (min 9 8) 7 5)) يا ’(max 4 (min 9 8) 7 5)
قبلاً گفتيم كه مفسر Lisp يك تابع يكتايي پيشساخته است كه eval نام دارد. آن صريحاً آرگومانهايش را وادار ميكند تا مطابق قوانين مذكور در بالا ارزيابي شوند. در بعضي حالات، آن ميتواند مقابل تابع quote قرار بگيرد بنابراين به وضوح لازم است كه يك ليست بعنوان داده مشخص شود تا سيستم Lisp بتواند يك فراخواني تابع تفسير شود، ما ميتوانيم(eval ’(max 4 (min 9 8) 7 5)) را مشخص كنيم كه مقدار 8 را بطوري كه در بالا توصيف شد بر ميگرداند. به همان صورت مشخص كردن (eval ’(peter walks home)) سبب يك خطاي Lisp ميشود زيرا Lisp سعي ميكند يك تابع peter فراخواني كند. مزيت اصلي رفتار برنامهها بعنوان داده اين است كه ما ميتوانيم برنامههاي Lisp (توابع) را طوري تعريف كنيم كه قادر به ساخت يا توليد برنامهها باشند بطوريكه ابتدا ليست نمايش متناظر را ساخته و سپس با استفاده از تابع eval ، مفسر Lisp را به منظور ارزيابي ليست ايجاد شده بعنوان يك تابع فراخواني ميكند. شگفتآور نيست كه به اقتضاي اين خصوصيات، Lisp هنوز زبان برنامهنويسي برتر در زمينه برنامهنويسي ژنتيك AI است.
وقتي مقادير را به نمادها تخصيص ميدهيم كه برنامهنويسي برنامههاي كاربردي
real-life به ذخيره مقاديري محاسبه شده در يك متغير نياز داشته باشد تا اگر در آينده در برنامه ديگري نياز باشند از هزينه محاسبه مجدد آن جلوگيري شود. در يك نگارش كاملاً تابعي Lisp مقدار يك تابع تنها به تعريف تابع و مقدار آرگومانهايش در فراخواني بستگي دارد. براي اينكه Lisp را يك زبان كاربردي بكنيم (كاربردي حداقل در اين مفهوم كه بتواند بر روي كامپيوترهاي وان نيومن به خوبي اجرا شود)، ما نياز به روشي داريم تا مقادير را به نمادها تخصيص دهيم.common Lisp با يك تابع پيشساخته بنام Setq ميآيد. Setq دو آرگومان ميخواهد: نماد (بنام متغير) كه يك مقدار به آن متصل شده است و يك عبارت نمادين كه بايد مقداري را فراهم كند. مفسر Lisp ارزيابي Setq را در روش خاصي انجام ميدهد بطوريكه آرگومان اول Setq را ارزيابي ميكند(متغير)، اما مقدار آرگومان دوم Setq را به متغير متصل ميكند(براي فهم چگونگي اتصال يك مقدار به يك نماد نياز به جزئيات فني زيادي خواهيم داشت كه در اين معرفي كوتاه نميتوان به آن پرداخت). مقدار آرگومان دوم Setq مقدار Setq را بر ميگرداند. اينها مثالهايي هستند:
?color
error: unbound symbol color
?(setq color ’green)
green
?(setq max (max 3 2 5 1))
3
توضيح اينكه در واقع Setq حالت مفسر Lisp را تغيير ميدهد تا دفعه بعدي كه همان متغير استفاده ميشود، داراي مقدار بوده و بنابراين مفسرLisp قادر به بازگرداندن آن خواهد بود. اگر اين اتفاق نيفتد آنگاه مفسر Lisp يك اخطار خواهد داد زيرا نماد متصل نشده است.
(گام 2 مفسر Lisp پيدا نشد). بنابراين آن ميگويدكه Setq يك اثر جانبي توليد ميكند زيرا حالت مفسر Lisp بطور پويا تغيير ميدهد. وقتي استفاده از Setq اجباري شد، به هرحال متوجه شد كه در واقع از مسير semantics (معاني) Lisp ناب دور ميشود. پس Setq بايد با دقت بسيار استفاده شود.
__________________
مرا سر نهان گر شود زير سنگ -- از آن به كه نامم بر آيد به ننگ
به نام نكو گر بميــرم رواست -- مرا نام بايد كه تن مرگ راست
|