(اساساً) شامل دستكاري نمادها است نه اعداد. اين نمادها ميتوانند اشياء در جهان و ارتباط بين آن اشياء را نشان دهند- ساختارهاي پيچيده نمادها نياز به دانش ما از جهان دارند. واژه ساختار اساسي دادهها در Prolog واژهاي است كه ميتواند يك ثابت، يك متغير يا يك ساختار باشد. ساختارها موضوعات ريز محاسبات گزارهاي را نشان ميدهند و شامل يك عملگر نام و يك پارامتر ليست هستند.
زبانهاي برنامهنويسي هوش مصنوعي(AI) ابزار اصلي بررسي و ساخت برنامههاي كامپيوتري هستند كه ميتوانند در شبيهسازي فرايندهاي هوشمند مانند يادگيري، استدلال و فهم اطلاعات نمادين بكار بروند. هر چند اخيراً زبان كامپيوتر اصولاً براي استفاده از كامپيوترها براي انجام محاسبات با اعداد طراحي شده بود، اما بزودي دريافتند كه رشتهاي از بيتها نه تنها اعداد بلكه ميتوانند اشياي دلخواه را نيز نمايش دهند. عمليات روي ويژهگيها يا نمادها ميتواند با استفاده از قوانين براي ايجاد، انتساب يا دستكاري نشان داده شود. اين تصور از محاسبات نمادين بعنوان تعريف الگوريتمهايي كه هر نوع اطلاعات را پردازش ميكنند و بنابراين ميتواند براي شبيهسازي هوش انسان بكار برود مناسب است.
بزودي برنامه نويسي با نمادها كه نياز به سطح بالايي از چكيدگي دارند توليد ميشوند، غير از امكاناتي كه با زبانهاي برنامه نويسي مخصوص پردازش اعداد ممكن بود مانند فرترن
I-زبانهاي برنامه نويسي AI
در AI خودكار كردن يا برنامهنويسي همه جنبههاي شناخت انساني بوسيله بنيادهاي شناخت علمي روشهاي نمادين و غير نمادين AI، پردازش زبان طبيعي، ديد كامپيوتري و سيستمهاي تكامل يا سازگار مطرح ميشود. لازم است دامنه مسئلههاي خيلي پيچيده در ابتداي مرحله برنامهنويسي يك مسئله AI معين، مشخص شود كه كافي نيست. تنها بوسيله تعامل و افزايش اصلاحات خصوصيات بسيار دقيق ممكن است. در حقيقت مسئلههاي معمول AI به بسياري از زمينههاي خاص گرايش دارند، بنابراين روشهاي ذهني بايد بوسيله توليد و آزمايش روشها بطور تجربي توسعه يابند(مشهور به نمونه سازي سريع). در اينصورت برنامهنويسي AI بطور قابل توجهي با روشهاي استاندارد مهندسي نرمافزار متفاوت بوده زيرا برنامهنويسي معمولا از يك مشخصات رسمي با جزئيات شروع ميشود. در برنامهنويسي AI پيادهسازي در واقع جزئي از پردازش مشخصات مسئله است. به اقتضاي طبيعت مسئلههاي AI برنامهنويسي AI مزاياي بسياري دارد اگر زبانهاي برنامه نويسي، برنامهنويسAI را آزاد بگذارند و در بسياري از ساختارهاي فني محدود نكنند (مانند ساختار انواع دادهاي جديد سطح پايين، دستيابي دستي به حافظه). ترجيحاً سبك برنامهنويسي اعلاني براي استفاده در ساختارهاي پيشساخته دادهاي سطح بالا(مانند ليستها و درختها) و عمليات(مانند تطبيق الگوها) مناسب است، بنابراين محاسبات نمادين سطح خلاصهسازي بيشتري نسبت به آنچه كه با زبانهاي دستوري استاندارد مانند فرترن، پاسكال يا C امكانپذير خواهد بود را پشتيباني ميكند. البته طبقهبندي خلاصه سازي آسان نيست، زيرا تدوين برنامههاي AI روي كامپيوترهاي استاندارد وان نيومن نميتواند به كارآمدي زبانهاي دستوري باشد. هر چند يك مسئله مسلم AI فهم آن است (حداقل جزئيات) امكان دارد با تنظيم مجدد آن به شكل خصوصيات جزئي شده با بكار بردن يك زبان دستوري پياده سازي مجدد شود. با توجه به نيازمنديهاي محاسبات نمادين و برنامهنويسي AI دو الگوي جديد برنامهنويسي كه به سبك دستوري پيشنهاد ميشوند بوجود ميآيد: سبك برنامهنويسي تابعي و منطقي. هر دو بر مبناي رياضيات طرحريزي شدهاند، يعني نظريه توابع بازگشتي و منطق رسمي. اولين زبان برنامهنويسي AI كاربردي كه هنوز هم بطور گسترده استفاده ميشود زبان برنامهنويسي Lisp است كه در اواخر دهه 1950 توسط جان مك كارتي توسعه يافته است. Lisp برمبناي نظريه توابع رياضي و خلاصهسازي Lambda است. تعدادي از كاربردهاي مهم و موثرAI در Lisp نوشته شده است. كه ما بعضي از جزئيات اين زبان برنامهنويسي را در اين مقاله شرح خواهيم داد. در اوايل دهه 1970 يك الگوي برنامهنويسي جديد بنام برنامهنويسي منطقي بر اساس محاسبات گزارهاي بوجود آمد. اولين و مهمترين زبان برنامهنويسي منطقي Prolog است كه توسط آلن كالمرار، رابرت كوالسكي و فيليپ راسل توسعه يافته است. مسئلهها در prolog بصورت حقايق، بديهيات و قوانين منطقي براي استنباط حقايق جديد بيان ميشوند. Prolog با قانون رياضي در محاسبات گزارهاي و نتايج نظري بدست آمده در زمينه اثبات قضيه خودكار در اواخر دهه 1960 بنا نهاده شده است.
II- برنامه نويسي تابعي
يك تابع رياضي نگاشتي از يك مجموعه (دامنه) به مجموعه ديگر(برد) است. تعريف يك تابع توصيف اين نگاشت است كه يا بطور صريح بوسيله شمارش و يا بطور ضمني بوسيله يك عبارت است. تعريف يك تابع بوسيله نام تابع كه بدنبال آن ليستي از پارامترها در داخل پرانتز قرار دارند و به دنبال آن نيز عبارت توصيفي نگاشت است مشخص مي شود مانند:
X يك عدد حقيقي است cube(X) ≡ X X X , where X is a real number.
آلونسو چارچ توابع بي نام را با استفاده از نمادLambda معرفي مي كند. يك عبارت Lambda پارامترها و نگاشت تابع را با استفاده از عملگر X مشخص مي كند, مانند λ (X)X X X آن خودش تابع است, بنابراين شرح بكار رفته در مثال تابع بي نام با يك آرگومان مشخص است. براي مثال:(λ (X) X X X)(4).
برنامه نويسي در يك زبان تابعي شامل ساختمان تعريف توابع و بكاربردن كامپيوتر براي ارزيابي عبارات است. يعني بكاربردن توابع با آرگومانهاي واقعي. كار اصلي برنامه نويسي پس از ساخت يك تابع براي يك مساله خاص تركيب توابع تعريف شده قبلي با توجه به اصول رياضي است. كار اصلي كامپيوتر ارزيابي توابع فراخواني شده و چاپ حاصل مقادير تابع است. در اين روش كامپيوتر مشابه يك كامپيوتر جيبي معمولي بكار مي رود البته بسيار انعطاف پذيرتر و قدرتمندتر. يك خاصيت برنامه نويسي تابعي اين است كه اگر عبارت به خوبي مقداردهي شود آنگاه ترتيب انجام ارزيابي كامپيوتر در نتايج ارزيابي تاثيري ندارد. بنابراين نتيجه ارزيابي يك عبارت تنها مقدار آن است. بدين معني است كه در يك زبان تابعي ناب اثرات جانبي وجود ندارد. اثرات جانبي در مدل موقعيت هاي حافظه به متغيرها متصل شده اند.بنابراين در يك زبان برنامه نويسي ناب در مفهوم زبانهاي دستوري متغير وجود ندارد. روشهاي اصلي كنترل جريان، بازگشت (تكرار) و عبارات شرطي هستند. اين كاملاً با زبانهاي دستوري در مفهوم اساسي كنترل ترتيب و تكرار متفاوت است. برنامه نويسي تابعي نيز خصوصيات توابع مرتبه بالا را پشتيباني مي كند. تابع مرتبه بالا تعريف تابعي است كه اجازه مي دهد آرگومانها يا مقدار بازگشتي تابع, مقدار توابع باشند. همه اين جوانب با هم مخصوصاً آخري از اصلي ترين مزاياي سبك برنامه نويسي تابعي در برابر سبك برنامه نويسي دستوري هستند. خلاصه برنامه نويسي تابعي سطح بالايي از درجه پيمانه اي بودن را فراهم مي كند. وقتي يك مسئله با تقسيم آن به مجموعه اي از زير مسئله ها تعريف مي شود, موضوع اصلي روشهايي است كه مي توان زير مسئله ها را به يكديگر چسباند. بنابراين براي افزايش قابليت پيمانه اي بودن يك مسئله مفهومي, ابتدا بايد نوع جديدي از چسب در زبان برنامه نويسي فراهم شود- قدرت اصلي برنامه نويسي تابعي .
III- برنامه نويسي تابعي در Lisp
Lisp اولين زبان برنامه نويسي تابعي است: آن براي پشتيباني محاسبات نمادين با استفاده از ليستهاي پيوندي بعنوان ساختار مركزي داده ها ابداع شده بود ( Lisp يعني پردازشگر ليست). جان مك كارتي دريافت كه روشهاي كنترل جريان توابع رياضي (بازگشت و تكرار) وسيله نظري مناسبي براي انجام محاسبات نمادين هستند. علاوه براين مفاهيم خلاصه سازي تابعي و كاربرد تابعي تعريف شده در محاسبات Lambda , سطح بالايي از خلاصه سازي موردنياز براي مسئله هاي AI مشخص شده را فراهم مي كنند.
Lisp در سال 1958 توسط مك كارتي ابداع شد و اولين نگارش محيط برنامه نويسي Lisp در سال 1960 آماده شد كه شامل يك مفسر, يك كامپايلر و مكانيسم تخصيص و بازپسگيري حافظه پويا بود (بعنوان مجموعه فضاي هرز شناخته شده است). يكسال بعد اولين زبان استاندارد با نام Lisp1.5 معرفي شد. پس از آن تعدادي از نسخه ها و محيط هاي برنامه نويسي Lisp توسعه يافته اند. مانند MacLisp، FranzLisp، InterLisp، CommonLisp، Scheme هر چند آنها در بعضي جزئيات خاص متفاوتند ولي هسته Syntax (نحو) و Semantic (معني) آنها اساساً يكسان است. هسته را در جاي ديگر معرفي خواهيم كرد. پر استفاده ترين نسخههاي
Lisp ، Common Lisp و scheme هستند. در اين مقاله ما Common Lisp را براي نشان دادن جنبه هاي مختلف Lisp با مثالهاي معمولي انتخاب كرده ايم. هرچند مثالها نيز به راحتي مي توانند در نسخه هاي ديگر Lisp سازگار شوند.
Syntax .A. (نحو) و semantics (معاني) Lisp
1. عبارات نمادين: عناصر نحوي Lisp عبارات نمادين ناميده مي شوند (كه به صورتS-expressionsشناخته شدهاند). داده ها و توابع (يعني برنامه هاي Lisp ) بصورت عبارات نمادين نشان داده شده اند كه مي توانند اتم ها يا ليست ها باشند. اتم ها كلمه اي شبيه اشيا هستند. اتمها وابسته به نوع كاراكترهايي كه براي شكل دادن يك اتم مجازند مي توانند به انواع مختلفي تقسيم شوند. انواع اصلي عبارتنداز:
Numbers:1 234-43.14159265358979 -7.5 6.02E+23
Symbols:SymbolSym23another-one t false NILBLUE
Strings: ”This is a string””977?” ”setq””He said: \” I’m here.\” ”
توضيح اينكه هرچند نماد خاصي مثل BLUE استفاده ميشود چون مفهوم مشخص براي برنامهنويسي دارد، اما بزودي Lisp تنها ترتيبي از حروف يا تنها يك نماد است. ليستها بندي شبيه اشياء هستند. يك ليست شامل يك پرانتز باز( دنبالهاي از اعداد دلخواه كه بوسيله فاصله خالي از هم جدا ميشوند) و يك پرانتز بسته هستند. هر عنصر ليست ميتواند يك اتم يا ليست باشد. اينها مثالهايي از ليستها هستند:
(This is a list) ((this) ((too))) () (((((((())))))))
(a b c d) (john mary tom) (loves john ?X)
(* (+ 3 4) 8) (append (a b c) (1 2 3))
(defun member (elem list)
(if (eq elem (first list)) T
(member elem (rest list))))
توضيح اينكه در بسياري از مثالها عناصر ليست خود ليستها هستند.چنين ليستهايي، ليستهاي تو در تو ناميده ميشوند. در مورد تو در تويي محدوديتي وجود ندارد. براي مثال يكي از قويترين Lisp ها را شرح ميدهيم: پيچيدهترين اشياء را به راحتي ميتوان نوشت. تنها چيزي كه در نظر گرفته ميشود درستي عدد داخل پرانتزهاست. مهم توضيح اين است كه معني وابسته به يك ليست نمايش ويژه يا اتم در ليست نمايش وارد نميشود. به اين معني كه همه عبارات نمادين كه در بالا توصيف شده است از لحاظ نحو برنامههاي Lisp را اصلاح ميكنند ولي الزاماً از لحاظ معني (semantic) برنامهها رااصلاح نميكنند.
2. Semantics (معاني): هسته هر سيستم برنامهنويسي Lisp مفسر است كه كارش محاسبه مقدار براي يك عبارات نمادين داده شده است. اين فرآيند ارزيابي نام دارد. نتيجه يا مقدار يك عبارت نمادين، يك عبارت نمادين است. كه بعد از كامل شدن ارزيابي برگردانده شده است. توضيح اينكه در واقع Lispداراي Semantics (معاني) عملياتي است كه با يك تعريف رياضي دقيق از نظريه تابع بازگشتي بدست ميآيد.
حلقه خواندن- محاسبه- چاپ چگونه ميتواند مفسر Lisp را فعال كرده و براي محاسبه عبارات نمادين و بنابراين اجراي واقعي برنامههاي Lisp بكار برود؟
مسئلههاي Prolog بصورت حقايق، بديهيات و قوانين منطقي براي استنباط حقايق جديد بيان مي شوند . Prolog با قانون رياضي در محاسبات گزاره اي و ونتايج نظري بدست آمده در زمينه اثبات قضيه خودكار در اواخر دهه1960 بنا شده است. مفسر Lisp در واقع بعنوان يك تابع معمولاً بنام eval و جزئي از هر محيط برنامهنويسي Lisp است تعريف شده است (مانند تابعي كه پيشساخته نام دارد). آن بوسيله فراخواني حلقه خواندن- محاسبه- چاپ در يك سيستم Lisp جاسازي ميشود، وقتي يك عبارت نمادين توسط كاربر داده مي شود ابتدا به داخل سيستم Lisp خوانده ميشود( خواندن هم يك تابع پيشساخته است). سپس مفسر Lisp كه via نام دارد تابع eval را فراخواني ميكند تا عبارت نمادين را محاسبه و نتيجه عبارت نمادين را با چاپ در دستگاه كاربر برگرداند ( شگفتآورنيست گفتن اينكه چاپ هم يك تابع پيشساخته است). وقتي سيستم Lispدر كامپيوتر شروع به اجرا ميشود اين حلقه خواندن- محاسبه- چاپ بطور خودكار شروع به اجرا كرده و بوسيله علامت ويژه اعلان Lisp در ابتداي خط جديد به كاربر علامت ميدهد در اين مقاله ما علامت سئوا ل (?) را به عنوان اعلان Lisp بكار خواهيم برد. براي مثال:
( 4 3 +) ?
7
هر وقت سيستم Lisp اجرا شود حلقه خواندن- محاسبه- چاپ فعال خواهد بود.
عبارت نمادين ( 4 3 + ) كه بوسيله هكر Lisp وارد شده است بوسيله مفسر Lisp بصورت فراخواني تابع جمع تفسير شده و نتيجه عبارت نمادين در ابتداي خط جديد 7 چاپ ميشود ارزيابي مفسر Lisp مطابق سه قانون زير انجام ميشود:
1- يكساني: يك عدد، يك رشته يا نمادهاي t و nil خودشان را ارزيابي ميكنند (بر ميگردانند) به اين معني كه ارزش عدد 3،3 و ارزش رشته ”house”، رشته ”house”است. نمادt مقدار t برميگرداند كه به معناي true تفسير ميشود وnil ، nil به معني false برميگرداند
2- نمادها: ارزيابي يك نماد عبارت نمادين مربوط به آن را برميگرداند. ( چگونگي اش را در زير نشان خواهيم داد) بنابراين اگر ما فرض كنيم نماد *names* به ليست
(john mary tom) وابسته است آنگاه ارزيابي *names* آن ليست را نتيجه ميدهد. اگر نماد color را به نماد green وابسته كنيم آنگاه green بعنوان مقدار color برگردانده ميشود.
به بيان ديگر نمادها بعنوان متغيرهايي كه به مقاديري متصل(باند) شدهاند تفسير ميشوند.
3- ليستها: هر ليست بعنوان يك فراخواني تابع تفسير ميشود. مفسر اول ليست دلالت بر تابعي دارد كه بايد براي بقيه عناصر( بالقوه خالي) كه آرگومانهاي آن تابع را نشان ميدهند بكار رود. در واقع آرگومانهاي يك تابع قبلا بصورت نمادهاي پيشوندي مشخص ميشوند. اين مزيت را دارد كه توابع به سادگي ميتوانند با تعداد دلخواهي آرگومان مشخص و استفاده شوند. ليست خالي ( ) داراي عبارت نمادين nil بعنوان مقدارش ميباشد. توضيح اينكه نماد nil در واقع داراي دو معني است: يك نمايش مقدار منطقي false و ديگري نمايش ليست خالي. هر چند ممكن است اين يك بيت فرد بنظر برسد، ولي در واقع در Lisp مشكلي در شناسايي مفهوم nil بكاررفته وجود ندارد.
ولي بطور كل آرگومانها قبل از اينكه توابع مقادير آنها را استفاده كنند ارزيابي ميشوند. اولويت ارزيابي ترتيبي از آرگومانها از چپ به راست است. يك آرگومان ممكن است يك اتم يا يك ليست باشد،درهر حالت بعنوان يك فراخواني تابع تفيسر شده و مفسر Lisp براي ارزيابي آن فراخواني ميشود. براي مثال، ارزيابي زير در سيستم Lisp يك تابع به حساب ميآيد:
?(max 4 (min 9 8) 7 5)
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 بايد با دقت بسيار استفاده شود.
- | سعید |
- | پنجشنبه سی ام آبان 1387
-
پیوند ها