B. نوع داده ليست
برنامهنويسي در Lisp در واقع به معني تعريف توابعي است كه روي ليست عمل ميكنند. مانند ايجاد، پيمايش،كپي، تغيير و حذف ليستها. از آنجايي كه اين در Lisp مركزي است، هر سيستم Lisp بر مبناي مجموعهاي از توابع پيشساخته ابتدايي كه بطور موثري عمليات اصلي ليست را پشتيباني ميكند ميآيد. ما بطور خلاصه يكي از مهمترين آنها معرفي ميكنيم. ابتدا نوع گزارهاي، ما ميدانيم كه يك عبارت نمادين جاري يا يك ليست است يا نيست (يعني يك اتم). اين كار بوسيله تابع Listp انجام ميشود كه هر عبارت نمادين expr را بعنوان آرگومان پذيرفته و اگر expr ليست باشد نماد t و در غير اين صورت nil برميگرداند. مثالها هستند (ما از فلش راست => براي نشان دادن نتيجه فراخواني تابع استفاده خواهيم كرد):
(listp ’(1 2 3))==>t
(listp ’( ))==>t
(listp ’3)==>nil
در انتخاب عناصر ليست دو تابع اساسي براي دستيابي به عناصر يك ليست وجود دارد: car وcdr هر دو تابع يك ليست را بعنوان آرگومان ميپذيرند. تابع car اولين عنصر ليست يا اگر ليست خالي از آرگومان باشد nil بر ميگرداند،و cdr همان ليست را بطوري كه عنصر اول آن حذف شده است يا اگر ليست خالي از آرگومان بود nil برميگرداند. مثالها:
(car ’(a b c)) ==>a (cdr ’(a b c)) ==>(b c)
(car ’( )) ==>nil(cdr ’(a)) ==>nil
(car ’((a b) c))==>(a b)
با استفاده از ترتيبي از فراخوانيهاي توابع car و cdr ميتوان يك ليست را از چپ به راست و از عناصر بيروني به سمت عناصر داخلي ليست پيمايش كرد.
براي مثال، در طول ارزيابي (car (cdr ’(see the quote))) مفسر Lisp ابتدا عبارت
(cdr ’(see the quote))را ارزيابي خواهد كرد كه ليست (the quote) را برميگرداند، سپس به تابع car پاس ميشود كه نماد the را بر ميگرداند. اينها مثالهايي ديگر هستند:
(car (cdr (cdr ’(see the quote)))) ==>quote
(car (cdr (cdr (cdr ’(see the quote))))) ==>nil
(car (car ’(see the quote))) ==>?
در طول ارزيابي مثال اخير چه اتفاقي خواهد افتاد؟ ارزيابي (car ’(see the quote)) نماد see را برميگرداند.سپس اين به عنوان آرگومان به فراخواني بيروني car پاس ميشود. چون تابع car يك ليست را به عنوان آرگومان مي پذيرد پس مفسر Lisp بلافاصله ارزيابي ديگر را با خطايي مانند اين خطا متوقف خواهد كرد: سعي ميشود Car SEE بدست آيد ولي Listp نيست. يك توضيح كوتاه تاريخي: نامهاي Car,cdr از روشهاي قديمي هستند زيرا آنها در اولين نگارش Lisp كه بر مبناي مجموعه عمليات كد ماشين كامپيوتر انتخاب و پياده سازي شده بودند (car از محتواي ثبات آدرس استفاده ميكند و cdr از محتواي ثبات كاهش استفاده ميكند). به منظور نوشتن كد Lisp خواناتر، common Lisp يا در تابع first و rest بوجود آمد. ما نامهاي قديمي را استفاده ميكنيم تا براي خواندن و فهم كد AI Lisp قديمي قادر باشيم. براي ساخت ليستها، يك تابع ابتدايي Cons مانند Car و cdr وجود دارد كه براي ساخت يك ليست بكار ميرود. Cons دو عبارت نمادين را ميپذيرد كه اولي بعنوان يك عنصر جديد در جلوي دومي وارد ميشود. در مثالهاي زير ملاحظه ميكنيد:
(cons ’a ’(b c)) ==>(a b c)
(cons ’(a d) ’(b c))==>((a d) b c)
(cons (first ’(1 2 3)) (rest ’(1 2 3))) ==>(1 2 3)
در اصل، Cons و ليست خالي با هم براي ساخت ليستهاي خيلي پيچيده كافي هستند، براي مثال:
(cons ’a (cons ’b (cons ’c ’( )))) ==>(a b c)
(cons ’a (cons (cons ’b (cons ’c ’( ))) (cons ’d ’( )))) ==>(a (b c) d)
چون اين كار كاملاً طاقتفرساست، سيستمهاي Lispبسياري با توابع ليست پيشساخته بسيار پيشرفته بوجود ميآيند. براي مثال، تابع List با تعداد دلخواهي عبارت نمادين يك ليست ميسازد، و تابع append با الحاق آرگومانهايش كه بايد ليست باشند يك ليست جديد ميسازد. equal تابعي است كه اگر عناصر و ترتيب آنها در دو ليست يكسان باشد t ، در غير اين صورت nil بر ميگرداند. مثال:
(list ’a ’b ’c) ==>(a b c)
(list (list 1) 2 (list 1 2 3)) ==>((1) 2 (1 2 3))
(append ’(1) (list 2)) ==>(1 2)
(append ’(1 2) nil ’(3 4))==>(1 2 3 4)
(equal ’(a b c) ’(a b c)) ==>t
(equal ’(a b c) ’(a c b)) ==>nil
__________________
مرا سر نهان گر شود زير سنگ -- از آن به كه نامم بر آيد به ننگ
به نام نكو گر بميــرم رواست -- مرا نام بايد كه تن مرگ راست
|