PDA

توجه ! این یک نسخه آرشیو شده میباشد و در این حالت شما عکسی را مشاهده نمیکنید برای مشاهده کامل متن و عکسها بر روی لینک مقابل کلیک کنید : طراحی و پیاده سازی زبانهای برنامه سازی :بررسی زبان لیسپ



بانوثریا
7th August 2010, 04:53 PM
آشنایی

لیسپ توسط جان مک کارتی و گروهی در موسسه تکنولوژی ماساچوست در حدود سال 1960 طراحی شد به طور گسترده برای پژوهش علم کامپیوتر به خصوص هوش مصنوعی بکار گرفته شد. در 30 سال گذشته نسخه های گوناگونی از این زبان طراحی شدند از بین همه زبان های موجود لیسپ زبانی است که استاندارد شده است و پیاده سازی خاصی از آن شهرت یافته است .
لیسپ از جهات بسیاری با زبان های دیگر متفاوت است. اغلب به شکل برنامه و داده ها در زبان بر می گردد که اجازه میدهد ساختمان داده ها به عنوان برنامه اجرا شوند و برنامه ها مثل داده ها اصلاح شوند. ویژگی دیگر آن تاکید بر بازگشتی به عنوان ابزار کنترل است.
محاسبات نمادین برنامه نویسیAI (هوش مصنوعی) شامل دستکاری نمادها است نه اعداد.این نماد ها میتوانند اشیا در جهان و ارتباط بین آن را نشان دهند- ساختارهای پیچیده نمادها نیاز به دانش ما از جهان دارند. واژه ساختار اساسی داده ها در lisp واژه ای است که می تواند یک ثابت، یک متغییر یا یک ساختار باشد. ساختارها موضوعات ریز محاسبات گزاره ای را نشان می دهند و شامل یک عملگر نام و یک پارامتر لیست هستند.
زبانهای برنامه نویسی هوش مصنوعی ابزار اصلی بررسی و ساخت برنامه های کامپیوتری هستند که می توانند در شبیه سازی فرایندهای هوشمند مانند یادگیری، استدلال و فهم اطلاعات نمادین بکار روند. هر چند اخیرا" زبان کامپیوتر اصولا" برای استفاده از کامپیوترها برای انجام محاسبات با اعداد طراحی شده بود، اما بزودی دریافتند که رشته ای از بیتها نه تنها اعداد بلکه می توانند اشیای دلخواه را نیز نمایش دهند. عملیات روی ویژگی ها یا نمادها می تواند با استفاده از قوانین برای ایجاد ، انتساب یا دستکاری نشان داده شود. این تصور از محاسبات نمادین بعنوان تعریف الگوریتمهایی که هر نوع اطلاعات را پردازش می کنند و بنابراین می تواند برای شبیه سازی هوش انسان بکار برود مناسب است.
درAI خودکار کردن یا برنامه نویسی همه جنبه های شناخت انسانی بوسیله بنیادهای شناخت علمی روشهای نمادین و غیر نمادین AI، پردازش زبان طبیعی، دید کامپیوتری و سیستمهای تکامل یا سازگار مطرح می شود. لازم است دامنه مسئله های خیلی پیچیده در ابتدای مرحله برنامه نویسی یک مسئله AI معین، مشخص شود که کافی نیست. تنها بوسیله تعامل و افزایش اصلاحات خصوصیات بسیار دقیق ممکن است. در حقیقت مسئله های معمول AI به بسیاری از زمینه های خاص گرایش دارند، بنابراین روشهای ذهنی باید بوسیله تولید و آزمایش روشها بطور تجربی توسعه یابند(مشهور به نمونه سازی سریع). در اینصورت برنامه نویسیAI بطور قابل توجهی با روشهای استاندارد مهندسی نرم افزار متفاوت بوده زیرا برنامه نویسی معمولا از یک مشخصات رسمی با جزئیات شروع می شود. در برنامه نویسی AI پیاده سازی در واقع جزئی از پردازش مشخصات مسئله است. به اقتضای طبیعت مسئله های AI برنامه نویسیAI مزایای بسیاری دارد اگر زبانهای برنامه نویسی، برنامه نویس AI را آزاد بگذارند و در بسیاری از ساختارهای فنی محدود نکنند (مانند ساختار انواع داده ای جدید سطح پایین، دستیابی دستی به حافظه). ترجیحا" سبک برنامه نویسی اعلانی برای استفاده در ساختارهای پیش ساخته داده ای سطح بالا(مانند لیستها و درختها) و عملیات(مانند تطبیق الگوها) مناسب است، بنابراین محاسبات نمادین سطح خلاصه سازی بیشتری نسبت به آنچه که با زبانهای دستوری استاندارد مانند فرترن،پاسکال یا سی امکان پذیر خئاهد بود را پشتیبانی می کند. البته طبقه بندی خلاصه سازی آسان نیست ، زیرا تدوین برنامه های AI روی کامپیوترهای استاندارد وان نیومن نمی تواند به کارآمدی زبانهای دستوری باشد. هرچند یک مسئله مسلم AI فهم آن است (حداقل جزئیات) امکان دارد با تنظیمات مجدد آن به شکل خصوصیات جزئی شده با بکار بردن یک زبان دستوری پیاده سازی مجدد شود.
با توجه به نیازمندیهای محاسبات نمادین و برنامه نویسی AI دو الگوی جدید برنامه نویسی که به سبک دستوری پیشنهاد می شوند بوجود می آید: سبک برنامه نویسی تابعی و منطقی. هر دو بر مبنای ریاضیات طرح ریزی شده اند، یعنی نظریه توابع بازگشتی و منطق رسمی. اولین زبان برنامه نویسیAI کاربردی که هنوز هم بطور گسترده استفاده می شود زبان برنامه نویسی lisp است.lisp بر مبنای نظریه توابع ریاضی و خلاصه سازی lambda است. تعدادی از کاربردهای مهم و موثرAIدرLisp نوشته شده است.

بانوثریا
7th August 2010, 04:54 PM
امکانات محیط برنامه نویسی و نحوه اجرای برنامه ها


Syntax(نحو) و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 mmber (elem list)


(if (eq elem (first list)) T


(membr elem (rest list))))

توضیح اینکه در بسیاری از مثالها عناصر لیستها هستند. چنین لیستهایی، لیستهای تو در تو نامیده می شوند. در مورد تو در تویی محدودیتی وجود ندارد. برای مثال یکی از قویترین lisp ها را شرح می دهیم: پیچیده ترین اشیاء را به راحتی می توان نوشت. تنها چیزی که در نظر گرفته می شود درستی عدد داخل پرانتزهاست. مهم توشضیح این است که معنی وابسته به یک لیست نمایش ویژه یا اتم در لیست نمایش وارد نمی شود. به این معنی که همه عبارات نمادین که در بالا توصیف شده است از لحاظ نحو برنامه های lisp را اصلاح می کنند ولی الزاما" از لحاظ معنی برنامه ها را اصلاح نمی کنند.


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 اجرا شود حلقه خواندن – محاسبه – چاپ فعال خواهدبود.
عبارت نمادین(+3 4) که بوسیله هکرlisp وارد شده است بوسیله مفسر lisp بصورت فراخوانی تابع جمع تفسیر شده و نتیجه عبارت نمادین در ابتدای خط جدید7 چاپ میشود ارزیابی مفسرlisp مطابق 3 قانون زیر انجام می شود:

1:یکسانی
یک عدد ، یک رشته یا نمادهای t,nil خودشان را ارزیابی میکنند به این معنی که ارزش عدد3،3 و ارزش رشته "house"، رشته" house" است . نمادt مقدار t بر می گرداند که به معنای فقعث تفسیر می شود و 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
در اینجا آرگومانها(min 9 8)7 5) هستند که دراولویتی قبل از تابعی به نام max که نتیجه مقادیر آرگومانها را بکار می برد ارزیابی می شوند.آرگومان اول 4، یک عدد است پس مقدار آن 4 است. آرگومان دوم(min 9 8) است که خودش یک فراخوانی تابع است. بنابراین باید قبل از آرگومان سوم فراخوانی شود،(min 9 8) باید توسط مفسر lisp ارزیابی شود چون ما باید مفسرlisp را برای بعضی آرگومانها در طول ارزیابی همه فراخوانی های توابع استفاده کنیم می توان گفت مفسرlisp بصورت بازگشتی فراخوانی شده است . مفسرlisp همان مراحل را به کار می برد، پس آرگومان اول 9 قبل از آرگومان دوم8 ارزیابی می شود. با کار برروی تابعmin حاصل8 می شود یعنی تابع کوچکترین عدد یک مجموعه از اعداد صحیح را محاسبه می کند. برای تابع بیرونی max هم به این معنی است که آرگومان دوم آن 8 ارزیابی می شود.
آرگومانهای بعدی 5و7هستند که نتیجه ارزیابی آنها مقادیر 5و7 می شود.حال تابع بزرگترین عدد که max نام دارد می تواند ارزیابی شود که مقدار8 برمی گرداند. این مقدار نهایی، مقدار فراخوانی همه توابع می باشد. از آنجایی که گفته می شود مفسر lisp همیشه سعی می کند مقدار یک نماد یا تفسیر یک لیست بعنوان یک فراخوانی تابع را تشخیص دهد ما چگونه می توانیم با نمادها و لیستها بعنوان داده رفتار کنیم؟ برای مثال،اگر ما لیست (peter home walks) را وارد کنیم ، آنگاه مفسر lisp فورا" یک خطا می دهد که چیزی شبیه این خطا می گوید : تابع peter ناشناخته است یا اگر ما فقط houseرا وارد کنیم،آنگاه مفسرlisp با خطایی شبیه این خطا خاتمه می یابد مقداری به house متصل نیست.حل این مسئله کاملا" آسان است زیرا عنصر اصلی هر لیست بعنوان نام تابع تفسیر می شود، هر سیستم lisp با یک تابع پیش ساخته quote می آید که یک عبارت نمادین را بعنوان آرگومان پذیرفته و این عبارت نمادین را بدون ارزیابی آن بر می گرداند.
برای مثال: لیست((quote(peter walks home)، به سادگی مقدار (peter walks home) را بر می گرداند، و برای (quote house) ،house را بر می گرداند. از آنجایی که تابع qute زیاد استفاده می شود، می توان آن را با کاراکتر ویژه ' بیان کرد. بنابراین برای مثال بالا می توانیم معادل(home peter walks)' وhouse' را مشخص کنیم. برنامه ها بعنوان داده، یعنی تابع quote به ما امکان می دهد تا با فراخوانی تابع بعنوان داده رفتار کنیم.
برای مثال:


(max 4(min 9 8) 7 5)'یا((min 9 8 )7 5) ute(max 4)
قبلا گفتیم که مفسر lispیک تابع یکتایی پیش ساخته است که eval نام دارد.آن صریحا" آرگومانهایش را وادار می کند تا مطابق قوانین مذکور در بالا ارزیابی شوند. در بعضی حالات، آن می تواند مقابل تابعquote قرار بگیرد بنابراین به وضوح لازم است که یک لیست بعنوان داده مشخص شود تا سیستم lisp بتواند یک فراخوانی تابع تفسیر شود،ما می توانیم (9max 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


?(setqmax(max 3 2 5 1))


3
توضیح اینکه در واقع setq حالت مفسرlisp را تغییر می دهد تا دفعه بعدی که همان متغییر استفاده می شود، دارای مقدار بوده و بنابراین مفسر lisp قادر به بازگرداندن آن خواهد بود. اگر این اتفاق نیفتد آنگاه مفسر lisp یک اخطار خواهد داد زیرا نماد متصل نشده است.(گام 2 مفسر lisp پیدا نشد). بنابراین آن می گوید که setq یک اثر جانبی تولید می کند زیرا حالت مفسرlisp به طور پویا تغییر می دهد. وقتی استفاده از setq اجباری شد، به هر حال متوجه شد که در واقع از مسیرsemantics(معانی)lisp ناب دور می شود. پس setq باید با دقت بسیار استفاده شود.

بانوثریا
7th August 2010, 04:55 PM
تعریف توابع جدید
برنامه نویسی در lisp با تعریف توابع جدید انجام می شود. در اصل این به این معنی است که مشخص کردن لیستها در یک روش نحوی معین. مشابه تابع setq که بوسیله مفسر lisp در یک روش خاص رفتار می کرد. تابع خاصdefun است که برای ایجاد اشیای تابع جدید توسط مفسرlisp بکار می رود.defun یک نماد دال برنامه تابع، یک لیست از پارامترها (ممکن است خالی باشد) برای تابع جدید و تعداد دلخواهی از عبارات نمادینی که بدنه تابع جدید را تعریف می کند را به عنوان آرگومانهایش می پذیرد. این تعویض از یک تابع ساده به نام my-sum است که دو آرگومان می پذیرد و با استفاده از تابع پیش ساخته آنها را جمع می کند.


(defun my-sum(x y)


(+ x y))
این عبارت به همان روشی که به عنوان یک تابع فراخوانی می شود در سیستم lispوارد می شود. ارزیابی یک تعریف تابع نام تابع را بعنوان مقدار برمی گرداند، اما یک شی تابع را بعنوان اثر جانبی ایجاد خواهد کرد و وقتی lispشروع به اجرا می کند آن را به مجموعه تعاریف توابع شناخته شده توسط سیستم lispاضافه می کند
توضیح اینکه در این مثال بدنه شامل تنها یک عبارت نمادین است. هر چند بدنه می تواند شامل ترتیب دلخواهی از عبارات نمادین باشد مقدار آخرین عبارت نمادین از بدنه مقدار تابع را تعیین می کند. به این معنی است که در واقع همه عناصر بدنه بی تاثیر هستند مگر اینکه اثرات جانبی تصمیم گیری تولید کنند.
لیست پارامترتابع جدیدmy-sum به ما می گوید وقتی فراخوانی می شود درست دو عبارت نمادین را بعنوان آرگومان می پذیرد. بنابراین اگر شما(my –sum 3 5) را در سیستم lisp وارد کنید مفسرlisp قادر خواهد بود که تعریف برای نام تابع مشخص شده را بیابد و سپس آرگومانهای داده شده را از چپ به راست پردازش کند وقتی این کار انجام شد آن مقدار هر آرگومان را مطابق پارامتر مشخص شده در لیست پارامترتعریف تابع وصل خواهد کرد در مثال نا بدین معنی است که مقدار آرگومان اول که 3 است به پارامتر x متصل می کند سپس مقدار آرگومان دوم که 5 است به پارامترy متصل می شود. چون مقدار یک آرگومان به یک پارامتر متصل می شود،این روش فراخوانی با مقدار نامیده شده است. بعد از مقداریابی برای همه پارامترها مفسرlisp قادر به ارزیابی بدنه تابع خواهد بود. مثال بدین معنی است که (+ 5 3) فراخوانی خواهد شد. نتیجه فراخوانی 8 است که به عنوان نتیجه فراخوانی(my-sum 3 5) برگردانده می شود. بعد از تکمیل فراخوانی تابع اتصالات موقت پارامترهای x ,y حذف می شوند. هنگامی که یک تابع جدید در سیستم lisp وارد می شود می تواند به عنوان جزئی از تعریف تابع جدید به همان روش که بعنوان تابع پیش ساخته استفاده شده است بکار برده شود. بطوریکه در مثال زیر نشان داده شده است.


(defun double-sum(x y)


(+(my – sum x y) (my-sum x yy)))
که با دو بار فراخوانی my – sum جمع آرگومانهایش را دو برابر خواهد کرد این مثال دیگری از یک تابع است نشان دادن استفاده از عبارات نمادین چندگانه در بدنه تابع است.


(defun hello-world() (print"hello world!")'done)
این تعریف تابع پارامتری ندارد زیرا لیست پارامترآن خالی است بنابراین وقتی (hello-world) فراخوانی می شود مفسرlisp بلافاصله ("!print "hello world) را ارزیابی و رشته "!hello world" را روی نمایشگر شما بعنوان یک اثر جانبی چاپ می کند سپس نمادdone' را ارزیابی خواهد کرد و done را به عنوان نتیجه فراخوانی تابع بر می گرداند.

بانوثریا
7th August 2010, 04:55 PM
تعریف ساختارهای کنترلی

هرچند اکنون تعریف توابع جدید با تعریف توابع پیش ساخته و توابعی که کاربر تعریف می کند ممکن است برنامه نویسی در lisp بسیار خسته کننده خواهد شد اگر کنترل جریان اطلاعات بوسیله شاخه های شرطی ممکن نبود شاید بارها تکرار شود تا اینکه یک روند توقف اجرا شود گزینش lisp بر مبنای ارزیابی توابع است توابع کنترل تستهایی روی عبارات نمادین واقعی انجام می دهد و ارزیابی عبارات نمادین متناوب را بسته به نتایج انتخاب می کنند تابع اساسی برای تعیین اثباتهای شرطی در lisp,cond است. Cond تعداد دلخواهی آرگومان را می پذیرد هر آرگومان یک بخش ممکن را بیان می کنند و به عنوان یک لیست نمایش داده شده که عنصر اول یک تست و بقیه عناصر اعمال (عبارات نمادین) هستند که اگر تست انجام شود ارزیابی می شوند مقدار آخرین عمل به عنوان مقدار پیشنهادی برگردانده می شود همه آرگومانهای ممکنcond(یعنی بخشها) تا زمانی که بخش اول بطور مثبت تست شود از چپ به راست ارزیابی می شوند در آن حالت مقدار آن بخش مقدار کل تابع cond است. در واقع این مفهوم بسیار پیچیده تر از آن است اجازه دهید تابع verbalize-prop زیر که یک مقدار احتمال را بیان می کند. به عنوان یک عدد حقیقی فرض می کنیم.


(defun verbalize-prop(prop-value)


(cond((>prob-value 0.75)'very-probable)


((>prob-value 0.5)'probable)


((>prob-value 0.25)'improbable)


(T'very-impobable)))
وقتی (verbalize – prop 0.33) فراخوانی می شود مقدار واقعی آرگومانها به پارامتر prop-value متصل می شود. سپس cond با آن اتصالات ارزیابی می شودvery-((prop-value<))'(probable است.> یک گزاره پیش ساخته است که تست می کند که آیا آرگومان اول از دومی بزرگتر است، چونpropvalue،0.33 است.به nil ارزیابی می شود که به معنی انجام نشدن تست است. بنابراین این بخش پیشنهادی بلافاصله پایان می یابد. و سپس پیشنهاد(prob-value 0,5)'probable<)) ارزیابی می شود که تابع تست باز هم nil بر می گرداند بنابراین ارزیابی هم پایان می یابد سپس prpp-value 0.25)))('improbable ارزیابی می شود حال با بکار بردن تابع تست T برگردانده می شود که به معنی انجام تست است. آنگاه همه اعمال این بخش که بطور مثبت تست شده است ارزیابی و مقدار آخرین عمل به عنوان مقدار cond برگردانده می شود در مثال ما تنها عمل 'improbable تعیین می شود که مقدار غیر محتمل را برمی گرداند از آنجایی که این مقدار cond را تعیین می کند و عبارت cond تنها عبارت بدنه تابع verbalize-propاست. نتیجه فراخوانی ((verbalize-prop،improbable 0.33) است توضیح اینکه اگر ما (verbalize –prop 0.1) را وارد کنیم مقدار very-improbable را بر می گرداند زیرا تست هر سه با شکست مواجه شده و باید با بخش (very-improbable't(ارزیابی شود در این حالت نماد t به عنوان تستی که همیشه t را برمی گرداند استفاده شده است بنابراین مقدار این پیشنهادvery-improbable است.

بانوثریا
7th August 2010, 04:55 PM
توابع مرتبه بالا
در lisp توابع می توانند بعنوان آرگومان استفاده شود تابعی که بتواند توابع را بعنوان آرگومانهایش بپذیرد تابع مرتبه بالا نامیده می شود. مشکلات فراوانی وجود دارند که یکی از پیمایش یک لیست(یا یک درخت یا یک گراف) است که باید برای هر لیست عنصر تابع معینی استفاده شود . برای مثال filter تابعی است که تستی برای عناصر لیست به کار می برد و آنهایی که شکست می خورند را حذف می کند. نگاشتها توابعی هستند که همان تابع را روی هر عنصر لیست به کار می برند تا لیستی از نتایج را برگردانند . تعاریف توابع مرتبه بالا می تواند برای تعریف توابع عمومی پیمایش لیست استفاده شود که آنها از توابع خاصی که برای پردازش عناصر لیست بکار می روند خلاصه می شوند . به منظور پشتیبانی تعاریف مرتبه بالا یک تابع خاص است که یک تابع و دنباله ای از آرگومانها را به عنوان آرگومان می پذیرد و آن تابع را در آرگومانهای آنها به کار می برد. به عنوان مثال با استفاده از funcall ، تابع عمومی filter را تعریف خواهیم کرد که می تواند به این صورت فراخوانی شود:


(6 3 1)<= =(filter '( 1 3 -9 -5 6 -3)#'plusp)
Plusp یک تابع پیش ساخته است که کنترل می کند آیا یک عدد داده شده مثبت است یا نه؟ اگر باشد آن عدد را بر می گرداند در غیر این صورت nil بر می گرداند نماد خاص # بکار می رود تا به مفسرlisp بگوید ک مقدار آرگومان یک شی تابعی است. تعریف به صورت زیر است:


(defun filter ( list test)


(cond ((null list) list)


((funcall test (car list))


(cons (car list)(filter (cdr list)test)))


(T (filter (cdr list)test))))
اگر لیست خالی باشد آنگاه بسادگی بر میگردد در غیر این صورت تابع تست روی عنصر اول لیست بکار می رود. اگر تابع تست موفق شودcons بکار می رود تا لیست حاصل را با استفاده از این عنصر و همه ی عناصری که در طول فراخوانی بازگشتی filter از cdr و تابع تست استفاده می کنند بسازد. اگر تابع تست برای عنصر اول با شکست مواجه شود این عنصر بسادگی با بکار بردن filter بصورت بازگشتی روی عناصر باقیمانده پرش می کند. یعنی این عنصر نمی تواند جزئی از لیست حاصل باشد تابع می تواند برای بسیاری از توابع مختلف تست استفاده شود مانند:


(filter '(1 3 A B 6 c 4) #'numberp)= =>(1 3 6 4)


(filter '(1 2 3 4 5 6)#'even)= =>(2 4 6)

به عنوان مثال دیگری از تعریف filter تابع مرتبه بالا، ما می خواهیم یک تابع نگاشت ساده تعریف کنیم که یک تابع روی همه عناصر یک لیست بکار رفته ، لیستی از همه مقادیر بر می گرداند. اگر تابعmy-map را فراخوانی کنیم آنگاه تعریفی شبیه این داریم:


(defun my-map(fn list)


(cond ((null list) list)


(T(cons(funcall fn(car list))(my-map fn(cdr list))))))
اگر یک تابع double وجود داشته باشد که تنها عدد را دو برابر کند آنگاه یم فراخوانی ممکنmy-map به این صورت می تواند باشد:


(8 6 4 2) < = =((my-map#'double'(1 2 3 4)
بارها شده که یک تابع باید یکبار استفاده می شد. بنابراین اگر ما بتوانیم مستقیما تعریفی از یک تابع بعنوان آرگومان از تابع نگاشت فراهم کنیم کاملا مناسب خواهد بود برای اینکار تعریف عبارت lambda را پشتیبانی می کند. در lispعبارات lambda با استفاده از نوع خاصی از lambdaتعریف می شوند نوع عمومی عبارت lambda به این صورت است:


(lambda(parameter…)body…)
یک عبارت lambda امکان می دهد تا ما تعریف تابع را از نام تابع تشخیص دهیم عباراتlambda می توانند به جای نام تابع در تابع funcall استفاده شوند مانند عبارت که تابع double ما می تواند باشد:


(lambda(x)(+xx))
برای مثال: فراخوانی تابع my-map بالا می تواند با استفاده از عبارت lambda مجددا" به صورت زیر بیان شود:


(my-map #'(lambda(x)(+xx))'( 1 2 3 4)= =>( 2 4 6 8)
یک عبارت lambda یک شی تابعی بر می گرداند که به نام تابع متصل نیست در تعریف my-map، پارامترfn را بعنوان متغییر نام تابع استفاده می کنیم. وقتی شکل lambda محاسبه شد مفسر lisp شی تابعی را به متغییر نام تابع متصل خواهد کرد. به این طریق یک پارامتر تابع بصورت یک نام تابع پویا استفاده می شود. نماد# ضروری است تا به lispبگوید که نه تنها یک شی تابعی را وصل کند بلکه باید اتصالات محلی و سراسری مقادیر وابسته به شی را نیز نگه دارد. این تنها با استفاده از عملگر quote امکان پذیر نخواهد بود.

بانوثریا
7th August 2010, 04:55 PM
مدل زبان و کاربردهای زبان

برنامه نویسی تابعی در lisp
Lisp اولین زبان برنامه نویسی تابعی است: آن برای پشتیبانی محاسبات نمادین با استفاده از لیستهای پیوندی بعنوان ساختار مرکزی داده ها ابداع شده بود(lisp یعنی پردازشگر لیست( جان مک کارتی دریافت که روشهای کنترل جریان توابع ریاضی (بازگشت و تکرار)وسیله نظری مناسبی برای انجام محاسبات نمادین هستند. علاوه براین خلاصه سازی تابعی و کاربرد تابعی تعریف شده در محاسبات lambda، سطح بالایی از خلاصه سازی مورد نیاز برای مسئله های AI مشخص شده را فراهم می کنند.
از کاربردهای این زبان می توان به هوش مصنوعی اشاره کرده تمایل به زبانهای هوش مصنوعی در دهه ی 1950 با ipl شروع شد ولی کاربردش توسط طراحی سطح پایین آن محدود شده است موفقیت بزرگ وقتی حاصل شد که جان مک کارتی از MIT زبان لیسپ را برای IBM 704 طراحی کرد لیسپ1.5 برای سالهای متوالی استاندارد شد لیسپ برای کارهای جستجو بسیار مناسب است. بازهای کامپیوتری و پردازش متن در لیسپ به خوبی پیاده سازی می شود. تفسیر ماشین خودکار که در آن رشته هایی از نمادها می تواند توسط رشته های دیگری جایگزین شود. زمینه ی دیگری برای کاربرد لیسپ محسوب می شود.

بانوثریا
7th August 2010, 04:56 PM
انقیادها زود رس یا دیررس- کنترل نوع ایستا یا پویا- تبدیل نوع ضمنی یا صریح


لیسپ دارای انقیاد دیررس می باشد زیرا قابلیت انعطاف موضوعی در پیاده سازی مهم است اغلب انقیاد ها در زمان اجرا صورت می گیرد.

کنترل نوع یعنی این که هر عملیاتی که در برنامه انجام می گیرد تعداد و نوع آرگومان های آن درست باشد. لیسپ کنترل نوع پویا دارد یعنی کنترل نوع آن در زمان اجرا انجام میشود.
لیسپ دارای تبدیل نوع ضمنی است زیرا دارای کنترل نوع پویاست و کنترل نوع پویا در نقطه ای از زمان اجرا که عدم تطابق به علت وجود انواع داده ای متنوعی که دارد رخ می دهد تبدیل ضمنی صورت می گیرد.

بانوثریا
7th August 2010, 04:56 PM
انواع داده های اولیه-نحوه تعریف یک متغییر از نوع آنها- پیاده سازی سخت افزاری یا نرم افزاری- انواع عملیات بر روی این انواع


اشیای داده اولیه در لیسپ عبارتند از : اتم و لیست. تعریف تابع و لیست های خاصیت انواع خاصی از لیست ها هستند که اهمیت ویژه ای دارند.آرایه ها،اعداد و رشته ها نیز وجود دارند ولی نقش چندانی ندارند.

متغییرها و ثوابت. اتم لیسپ نوع اولیه شی داده است. اتم را گاهی اتم لیترال نیز می نامند تا از عدد یا اتم عددی تفکیک شود از نظر نحوی اتم مثل شناسه، رشته ای از حروف و ارقام است که با حرف شروع می شود. تفاوتی بین حروف کوچک و بزرگ در نامگذاری شناسه نیست . در تعریف تابع ، اتمها مثل شناسه ها رفتار می کنند، یعنی به عنوان اسامی متغییرها،توابع،پارامتر مجازی و غیره به کار می روند.
اما اتم در زمان اجرا مثل شناسه نیست. اتم ، شی داده پیچیده ای است که در حافظه نمایش داده می شود و حافظه توصیفگر نوع و اشاره گری به لیست خاصیت است. لیست خاصیت شامل خواص گوناگون مربوط به اتم است که یکی از آنها نام چاپی آن است که یک رشته کاراکتری نمایش دهنده اتم برای ورودی خروجی است. سایر خواص،انقیادهای گوناگونی را برای اتم نمایش می دهند که ممکن است شامل نام تابع و سایر خواصی باشد که توسط برنامه در حال اجرا تعیین می شود.
وقتی اتمی به عنوان عنصری از شی داده دیگر مثل لیست باشد به وسیله اشاره گر به محلی از حافظه نمایش داده می شود که به عنوان نمایش زمان اجرای اتم عمل می کند. لذا هر مراجعه به اتمABC در حین اجرای برنامه لیسپ به صورت اشاره گر به همان محل حافظه منظور می شود.
هر اتم به عنوان عنصری در جدول مرکزی تعریفی سیستم،به نام لیست شی(ob-list)قرار می گیرد .ob_list به صورت جدول در هم سازی سازمان دهی می شود که نام چاپی را به طور کارآمد جستجو می کند و بازیابی اشاره گر به اتمی با آن نام چاپی را آسان می کند. به عنوان مثال وقتی لیستی ورودی است که حاوی رشته کاراکتری"ABC" است که نشان دهنده اتم ABC است. تابع readلیستob_list را برای"ABC" جستجو می کند که حاوی اشاره گر به حافظه اتم ABC است این اشاره گر در محل مناسبی از لیستی که ساخته می شود درج می گردد.
اعداد به شکل صحیح یا ممیز شناور قابل استفاده اند.از نمایش سخت افزاری استفاده می شود ولی نیاز به توصیفگر زمان اجراست. لذا هر عدد دو کلمه را اشغال می کند. این نمایش بخوبی با نمایشی که برای اتمهای لیترال به کار می رود تنظیم می شود. هر عدد یک اتم با تعیین کننده نوع و اشاره گری به رشته بیتی نمایش دهنده عدد است.
رته ها به صورت رشته هایی از نمادها نمایش داده می شود. کتیشن یگانه به عنوان تابع quote برای آرگومان های لیترال به توابع تفسیر می شود.

بانوثریا
7th August 2010, 04:59 PM
نوع داده لیست
برنامه نویسی در lispدر واقع به معنی تعریف توابعی است که روی لیست عمل می کنند. مانند ایجاد،پیمایش، کپی ، تغییر و حذف لیستها. از آنجایی که این در lisp مرکزی است، هر سیستم lisp بر مبنای مجموعه ای از توابع پیش ساخته ابتدایی که بطور موثری عملیات اصلی لیست را پشتیبانی می کند می آید.ما به طور خلاصه یکی از مهمترین آنها را معرفی می کنیمابتدا نوع گزاره ای ، ما می دانیم که یک عبارت نمادین جاری با یک لیست است یا نیست(یعنی یک اتم). این کار بوسیله تابعlisp انجام می شود که هر یک عبارت نمادین 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 ابتدا عبارت ((quote cdr '(see the) را ارزیابی خواهد کرد که لیست(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 نیست. یک توضیح کوتاه تاریخی: نامهایcdr,car از روشهای قدیمی هستند زیرا آنها در اولین نگارش lisp که بر مبنای مجموعه عملیات کد ماشین کامپیوتر انتخاب و پیاده سازی شده بودند(car از محتوای ثبات آدرس استفاده می کند وcdr از محتوای ثبات کاهش استفاده می کند). به منظور نوشتن کد lispخواناتر، common lisp یا در تابع first,rest بوجود آمد . ما نامهای قدیمی را استفاده می کنیم تا برای خواندن و فهم کدlisp AI قدیمی قادر باشیم. برای ساخت لیستها ، یک تابع ابتدایی 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( list1)2(list 1 2 3)) = =>((1)2(1 2 3))


(append '(1)(list2)) = = >( 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
لیست های خاصیت. هر اتم لیترال دارای لیست خاصیتی است که از طریق اشاره گری که در محل حافظه نمایش دهنده اتم ذخیره شده است قابل دستیابی است. لیست خاصیت یک لیست معمولی در لیسپ است با این تفاوت که عناصر آن جفتی از دنباله مقدار خاصیت/ نام خاصیت است. هر لیست خاصیت اتم حداقل شامل خاصیت pname است که مقدار وابسته آن اشاره گر به لیستی است که حاوی نام چاپی اتم به شکل کاراکتری است. اگر اتم نام تابع باشد لیست خاصیت آن حاوی نام خاصیت است که شامل نوع تابع و اشاره گر به لیست نمایش دهنده تعریف تابع است. برنامه نویس می تواند سایر خواص را در صورت لزوم اضافه کند . در اغلب برنامه های لیسپ لیستهای خاصیت اتمها ساختار مرکزی هستند که اغلب داده ها در آنها ذخیره می شوند.
لیسپ زبانی است که با مفسر نرم افزاری پیاده سازی می شود در این گونه پیاده سازی زبان مترجم کد ماشین را برای کامپیوتر تولید نمی کند در عوض مفسر شکل میانی از برنامه را تولید می کند که اجرای آن ساده تر از اجرای دستورات اولیه است و با کد ماشین فرق دارد. رویه تفسیر برای اجرای این برنامه ی ترجمه شده باید توسط نرم افزار نمایش داده شود زیرا مفسر سخت افزاری نمی تواند مستقیما مورد استفاده قرار گیرد استفاده از مفسر نرم افزاری منجر به برنامه هایی می شود که اجرای آنها کند تر است. علاوه بر این زبانهایی که مفسر نرم افزاری دارند تمایل به شبیه سازی اعمال اولیه مدیریت حافظه و سایر ویژگی های زبان دارند.


عملیات بر روی اتمها. عملیات بر روی اتمها شامل تابع تست atom است که بین اشاره گر به اتم تمایز قائل می شود( با کنترل توصیفگر کلمه). Numberp تست می کند آیا اتم یا اتم لیترال است یا اتم عددی. Eq تست می کند آیا دو اتم لیترال مساویند یا خیر.getnum اتم جدیدی تولید می کند( و آن را در ob_list قرار نمی دهد)intern را در ob_list قرار می دهد.remob اتمی را از ob_list حذف می کند.
لیست دارای عملیات اولیه +و-و*و/و... است نحو آنها مثل سایر عملیات لیسپ است. لذا a+b*c به صورت (+A(*BC)) نوشته می شود. تمام عملیات حسابی ، عملیات کلی اند، یعنی آرگومانهایی از نوع حقیقی یا صحیح را گرفته تبدیل نوع لازم را انجام می دهند.
عملیات رابطه ای zerop مقدار0 را تست می کند greaterp,lessp عملیات بزرگتر از و کوچکتر از را نشان می دهند. نتایج عملیات یا اتم nil است که نشانگر false است یاt است که نشانگر true است.
نوع داده بولین در لیسپ وجود ندارد عملیات بولین or,and,not به صورت تابع وجود دارند. عملیات and لیستی از آرگومانهای ارزیابی نشده را دریافت کرده، هر کدام را به نوبت ارزیابی می کند. اگر آرگومانهای آن nillباشند،nill را بر می گرداند. عملیات or نیز به همین روش عمل می کند.
عملیات برروی لیست ها. عملیات اولیه car,cdr عنصری از لیست را بازیابی می کنند. اگر لیست l به عنوان عملوند باشند،(car L) اشاره گر به لیستی را بر می گرداند که اولین عنصر آن حذف شده است.const دو آرگومان اشاره گر دارد ، یک کلمه حافظه عنصر لیست را تخصیص می دهد، دو اشاره گر را در فیلد های car,cdr کلمه ذخیره می کند و اشاره گر به کلمه جدید را بر می گرداند. اگر عملوند دوم لیسپ باشد، اولین عنصر در ابتدای این قرار می گیرد و اشاره گر به لیست جدید برگردانده می شود.car,cons,cdr عملیات اصلی برای انتخاب عناصر لیست و ساختن لیستها هستند. با استفاده از cons می توان هر لیستی را عنصر به عنصر ساخت. مثال زیر را ببینید:
(cons A(cons B(cons C nil))
این دستور لیستی با سه عنصر A,B,C می سازد. اگرL=(A B C) یک لیست باشد، آنگاه (car L) برابر با A،(car(cdr L)) برابر با Bوcar(cdr(cdr L))) برابر با C است. با استفاده درست از car,cdr,cons می توان هر لیستی را به اجزا سازنده آن تقسیم کرد و لیست جدیدی از آنها را ایجاد کرد .
عملیات list به جای دنباله ای از عملیات cons قرار می گیرد.list آرگومانهایی را گرفته لیستی از آن آرگومانها را درست می کند و اشاره گر به این لیست را بر می گرداند.
عملیات quote هر لیست یا اتمی را به صورت لیترال در برنامه می نویسند. عملیات replaca به جای car اشاره گر جدیدی را قرار می دهدreplaca برای تغییر اشاره گر cdr به کار می رود. این دو عملیات اولیه باید با دقت به کار برده شوند ، زیرا محتویات کلمه لیست را تغییر می دهند و مقدار را بر می گردانند و در نتیجه ممکن است اثرات جانبی داشته باشد.

عملیات بر روی لیست خاصیت. عملیاتی برای درج،حذف، و دستیابی به خواص موجود در لیست خاصیت منظور شده اند.put جفت مقدار خاصیت/ نام خاصیت را به لیست خاصیت اضافه می کند.get مقدار فعلی مربوط به نام خاصیتی را برمی گرداند.remprop جفت مقدار/نام را از لیست حذف می کند دستورات زیر را ببینید:


(put 'mary ' age 40)


(get 'mary 'age)


(remprop 'mary 'age)
دستور اول جفت(age 40) را به لیست اتمmary اضافه می کند دستور دوم خاصیت age را به بازیابی و دستور سوم خاصیت age را حذف می کند.

بانوثریا
7th August 2010, 05:00 PM
انواع داده مرکب
اوناع داده مرکب شامل رشته های کاراکتری ، اشاره گرها و فایل ها می باشند.
در لیسپ رشته های کاراکتری طول نامحدود وجود دارد. رشته می تواند با هر طولی باشد و در حین اجرای برنامه هم طول رشته می تواند تغییر کند.


نحوه پیاده سازی انواع ساختمان داده ها
اغلب پیاده سازی لیسپ نوع شی داده آرایه یا بردار را فراهم میکند اما یکنواختی اندکی بین پیاده سازی های مختلف وجود داردکه ناشی از عدم اهمیت بردارها و آرایه ها در اغلب برنامه های لیسپ است. نوع پیاده سازی لیسپ تابع mkvect(bound) را تدارک میبیند که شی داده بردار را با بازه 0 تاbound ایجاد می کند. هر عنصر بردار ممکن است شامل اشاره گر به شی داده لیسپ باشد. در آغاز تمام اشاره گرهاnil هستند. تابع getv(vector,subscript) اشاره گر ذخیره شده در عنصری را بر می گرداند که آرگومان به آن اشاره می کند.
توابع تعریفی برنامه نویس به شکل لیست هایی برای ورودی نوشته می شود. روال های ورودی لیسپ بین تعریف تابع و لیست های داده تماییز قائل نمی شوند اما تمام لیست ها را به نمایش لیست پیوندی تفسیر می کنند. هر اتم در ob_list جستجو می شوند و در صورت وجود اشاره گر به آن اتم بازیابی می شود و در صورت عدم وجود اتم جدیدی ایجاد می گردد.
لیست ساختمان داده ای است که دنباله مرتبی از ساختمان داده ها است.





مشخصات و نحو:
لیست ها همانند بردارها حاوی دنباله مرتبی از اشیا هستند . یعنی می توان به اولین عنصر و دومین عنصر و... مراجعه کرد. اولین عنصر لیست را معمولا راس می گویند. لیست ها از جهات زیر با بردارها متفاوت اند:
1. طول لیست ها به ندرت ثابت است . لیست ها معمولا برای نمایش ساختمان داده ها بکار می روند و در طول اجرای برنامه کوتاه و بلند می شوند
2. لیست ها بندرت همگن هستند نوع داده هر عنصر لیست ممکن است با عنصر دیگر متفاوت باشد
3. زبان هایی که از لیست ها استفاده می کنند نوعا چنین داده ای را به صورت ضمنی بدون صفحات صریحی برای اعضای لیست تعریف می کنند.
نحو زبان لیسپ ساختار لیست را به صورت زیر نمایش می دهد:


(functionname data1 data2 …. Datan)
لیسپ با اعمالfunctionname بر روی آرگومانهای data 1 تا data2 اجرا میشود.
اغلب عملیات در لیسپ آرگومانهای لیست را گرفته مقادیر لیست را بر میگردانند به عنوان مثال:cons دو آرگومان لیست را می گیرد و لیستی را برمیگرداند که آرگومان اول آن به ابتدای آرگومان دوم اضافه می شود:


(cons '( a b c)'(d e f)) =(( a b c) d e f)
این مثال نشان می دهد که نتیجه لیستی با 4 عنصر است که عنصر اول لیست (a b c) است . 4 عنصر لیست حاصل از یک نوع نیستند. اولی یک لیست است در حالی که بقیه عناصر اولیه یا اتم هستند.

بانوثریا
7th August 2010, 05:01 PM
پیاده سازی:
از ماهیت پویایی اغلب پیاده سازی های لیست این واقعیت که عناصر موجود در لیست به ندرت همگن هستند نتیجه می شود که مدیریت حافظه منظم که برای بردارها و آرایه ها مفید است در اینجا قابل استفاده نیست. در چنین مواردی معمولا از شازمان مدیریت حافظه پیوندی استفاده می شود. یک قلم لیست یک عنصر اولیه است که معمولا شامل شی داده ای به اندازه ثابت است. در لیست به 3 فیلد از اطلاعات نیاز داریم:
یک فیلد نوع و دو اشاره گر لیست. اگر فیلد نوع اتم باشد آنگاه فیلد های باقیمانده توصیفگرهایی هستند که این اتم را توصیف می کنند اگر فیلد نوع اتم باشد اگر فیلد نوع یک لیست باشد اشاره گر اول راس لیست است(اولین عنصر لیست) در حالی که اشاره گر دوم انتهای لیست است( اعضای باقیمانده ).
(cons '(a b c) ;(d e f))= ((a b c)d e f)
شکل های گوناگون لیست ها
پشته و صف ها:
پشته لیستی است که انتخاب ، درج و حذف عناصر از انتهای آن انجام میشود. صف لیستی است که انتخاب و حذف از یک طرف و درج از طرف دیگر انجام می شود. حافظه پشته و صف را می توان به صورت ترتیبی یا پیوندی نمایش داد.

درخت ها:
لیستی که عناصرش علاوه بر اشیای داده اولیه ممکن است لیست باشند درخت نام دارد به شرطی که هر لیست فقط یک عنصر از اولین لیست باشد.

گراف های جهتدار:
ساختمان داده ای که عناصر آن با استفاده از الگوی پیوندی خاصی به هم پیوند داده می شوند گراف چهتدار نام دارد.

بانوثریا
7th August 2010, 05:01 PM
لیست های خاصیت:
اگر در رکوردی با تعداد متغییری از عناصر تعداد عناصر بدون هیچ محدودیتی تغییر کند لیست خاصیت نام دارد. در لیست خاصیت اسامی عناصر و مقادیر آنها باید ذخیره شوند هر نام فیلد نام خاصیت نامیده می شود.مقدار متناظر فیلد مقدار خاصیت نامیده می شود نمایش متداول برای لیست خاصیت همان لیست پیوندی معمولی است به طوری که اسامی صف و مقادیر آنها در یک دنباله طولانی تغییر می کنند. برای انتخاب یک مقدار خاصیت مثلا مقدار خاصیت age لیست جستجو می شود تا خاصیت مطلوب پیدا شود برای اینکار فقط اسامی خاصیت ها بررسی می شوند. پس از یافتن خاصیت مطلوب عنصر بعدی لیست مقدار آن خاصیت است. وقتی خاصیت جدیدی در لیست خاصیت درج می شود دو عنصر درج می گردد که عبارتند از نام خاصیت و مقدارش. لیست های خاصیت در زبانهای برنامه نویسی به نامهای مختلفی خوانده می شوند.در زبان لیسپ به نام لیست خاصیت و جدول نامیده می شوند. لیست خاصیت- مقدار و لیست توصیفی نیز نامهای دیگری برای لیست خاصیت هستند.

عملیات اولیه در این زبان

عملیات برروی اتمها. عملیات برروی اتمها شامل تابع تستatom است که بین اشاره گر به atom تمایز قایل می شود (باکنترل توصیفگر کلمه). Numberp تست می کند آیا اتم یا اتم لیترال است یا اتم عددی. Eq تست می کند آیا دو اتم لیترال مساویند یا خیرgetnum اتم جدیدی تولید می کند(و آن را در ob_list قرار نمی دهد .) intern را در ob_listقرار میدهد.remobاتمی را ازob_list حذف می کند.
لیسپ دارای عملیات اولیه +و-و*و/ و.. است . نحو آنها مثل سایر عملیات لیسپ است . لذا a+b*c به صورت (A(*BC)) نوشته می شود.تمام عملیات حسابی، عملیات کلی اند،یعنی آرگومانهایی از نوع حقیقی یا صحیح را گرفته تبدیل نوع لازم را انجام می دهند.
عملیات رابطه ای zerop مقدار0(صفر) را تست می کند.greaterp,lessp عملیات "بزرگتر از" و "کوچکتر از" را نشان می دهند. نتایج این عملیات یا اتمnill است که نشانگر false است یاt است که نشانگر trueاست.

نوع داده بولین در لیسپ وجود ندارد. عملیات بولینnot,and, or به صورت تابع وجود دارند. عملیات and لیستی از آرگومانهای ارزیابی نشده را دریافت کرده، هر کدام را به نوبت ارزیابی می کند. اگر آرگومانهای آن nill باشند،nill را بر می گرداند. عملیات or نیز به همین روش عمل می کند.

عملیات بر روی لیست ها. عملیات اولیه car,cdr عنصری از لیست را بازیابی می کنند . اگر لیستl به عنوان عملوند باشند،(car l) اشاره گر به لیستی را بر می گرداند که اولین عنصر آن حذف شده است.const دو آرگومان اشاره گر دارد، یک کلمه حافظه عنصر لیست را تخصیص می دهد، دو اشاره گر را در فیلد هایcar,cdr کلمه ذخیره می کند و اشاره گر به کلمه جدید را برمی گرداند. اگر عملوند دوم لیسپ باشد، اولین عنصر در ابتدای این لیست قرار می گیرد و اشاره گر به لیست جدید برگردانده می شود.cdr,cons,car عملیات اصلی برای انتخاب عناصر لیست و ساختن لیستها هستند. با استفاده از cons می توان هر لیستی را عنصر به عنصر ساخت . مثال زیر را ببینیر:


(cons A(cons B(cons C nil))
این دستور لیستی با سه عنصر A,B,C می سازد. اگرL=( A B C)یک لیست باشد، آنگاه (car L) برابر با A،(car(cdr L)) برابر با B ،car(cdr L)))برابر باC است. با استفاده درست ازcons,cdr,car می توان هر لیستی را به اجزای سازنده آن تقسیم کرد و لیست جدیدی از آنها ایجاد کرد. عملیات listبه جای دنباله ای از عملیات cons قرار می گیرد.listآرگومانهایی را گرفته لیستی از آن آرگومانها را درست می کند و اشاره گر به این لیست را بر می گرداند.
عملیاتquote هر لیستی یا اتمی را به صورت لیترال در برنامه می نویسد. عملیات replaca به جای car اشاره گر جدیدی را قرار می دهد.replaca برای تغییر اشاره گرcdr بکار می رود. این دو عملیات اولیه باید با دقت به کار برده شوند، زیرا محتویات کلمه لیست را تغییر می دهند و مقدار را بر میگردانند و در نتیجه ممکن است اثرات جانبی داشته باشد.

عملیات بر روی لیست خاصیت. عملیات درج،حذف و دستیابی به خواص موجود در لیست خاصیت منظور شده اند.put جفت مقدار خاصیت/نام خاصیت را به لیست خاصیت اضافه می کند.get مقدار فعلی مربوط به نام خاصیتی را برمی گرداند.rempropجفت مقدار / نام را از لیست حذف می کند. دستورات زیر را ببینید:

(put `mary ` age 40)

(get `mary ` age)


(remprop `mary ` age)
دستور اول جفت(age 40) را به لیست اتم mary اضافه می کند. دستور دوم خاصیت age را به بازیابی و دستورسوم خاصیتage را حذف می کند.


مقداردهی اولیه و انتساب. انتساب مستقیم در لیسپ نقش کلیدی ندارد. اغلب برنامه های لیسپ بدون عملیات انتساب انجام می شوند ولی با استفاده از بازگشتی و انتقال پارامترها همان اثر را بطور غیر مستقیم اعمال می کنند. انتسابها در سگمنت هایprog به کار می روند که در آنجا برنامه های لیسپ شکل دستوری به خود می گرند. عملیات اصلی انتساب setq است. عبارت (setq x val) مقدار val را به متغییرx نسبت میدهد. نتیجه عبارت مقدارval است.(لذا setq یک تابع است ولی مقدارش نادیده گرفته می شود.)set مشابه setq است با این تفاوت که متغییری که انتساب به آن صورت می گیرد می تواند محاسبه شود.
برای مثال:

(set(car L)val) وقتی معادل(setq x val) است که اتم x اولین عنصر لیست L باشد.rplacd,rplace به ترتیب انتساب به فیلدهای car,cdr را ممکن میسازد.

برای مثال:
(rplace L val) مقدارval را به اولین عنصر L نسبت می دهد.





*

Format: (* <num1> <num2> ...)

Examples:

>(* 4 5 6)

120

>(* 123.5 12/3)

494.0

>(* (* 2 3) 8)

48

>(* 'a 1)

Error: A is not of type NUMBER.

Special cases:

>(* 3)

3

>(*)

1






+

Format: (+ <exp1> <exp2> ...)

Examples:

>(+ 4 5 6)

15

>(+ 123.5 12/3)

127.5

>(+ (* 2 3) 8)

14

>(+ 'a 1)

Error: A is not of type NUMBER.

Special Cases:

_Q

>(+ 3)

3

>(+)


0

بانوثریا
7th August 2010, 05:02 PM
نوع داده انتزاعی

لیسپ اولیه فاقد ویژگی انتزاع بود. اما فعلا داراری ویژگی CLOS است.
CLOS دارای ویژگی های زیر است:
1. وراثت چندگانه با استفاده از وراثت minx پشتیبانی می شود.
2. توابع کلی
3. شبه کلاس ها و شبه اشیا
4. تکنیک ایجاد و مقدار دهی اولیه منجر به کنترل فرایند توسط کاربر می شود.


نحوه تعریف و فراخوانی زیربرنامه ها- کنترل زیربرنامه ها- نحوه اختصاص حافظه به آنها – نخوه ارسال پارامترها- زیربرنامه های بازگشتی



در اغلب زبانهای کامپایلری مثل java,c++,c تعریف زیربرنامه مستقل از اجرای آن است . برنامه منبع توسط کامپایلر به شکل اجرایی در می آید در حین اجرای برنامه بخش ایستای تعریف زیربرنامه غیر قابل دستیابی و غیر قابل مشاهده است اما در زبان لیسپ که با مفسر نرم افزاری پیاده سازی می شود تمایزی بین این مرحله وجود ندارد با تعریف زیربرنامه ها می توان مثل اشیا داده زمان اجرا برخورد کرد.
ترجمه عملیاتی است که تعریف زیربرنامه را به شکل رشته کاراکتری گرفته و شی داده زمان اجرا را تولید می کند که این تعریف را نمایش می دهد. اجرا عملیاتی است که تعریف به شکل زمان اجرا را گرفته سلبقه فعالیتی را از آن ایجاد می کند و آن سابقه فعالیت را اجرا می نماید.
در لیسپ ترجمه عملیاتی است که ممکن است بر روی داده کاراکتر در زمان اجرا فراخوانی شود تا شکل اجرای بدنه زیربرنامه را تولید نماید این زبانها عملیاتی بنام defun دارند که بدنه زیر برنامه و مشخصات را گرفته یک تعریف قابل فراخوانی از زیر برنامه را ایجاد می کند بنابراین در زبان لیسپ می توان اجرای برنامه را بدون وجود هیچ زیربرنامه ای آغاز کرد در حین اجرای برنامه بدنه زیر برنامه ممکن است خوانده شود یا به شی داده کاراکتری ایجاد گردد و سپس به شکل اجرایی ترجمه شود ممکن است عملیاتdefun برای تهیه یک نام و تعریف پارامترها برای بده زیربرنامه مورد استفاده قرار گیرد به طوریکه تعریف کاملی به دست آید. زیربرنامه در صورت نیاز می تواند فراخوانی شود. تعریف زیربرنامه ممکن است اصلاح شود بنابراین در زبان لیسپ تعریف زیربرنامه یک شی داده است.

استفاده از پشته در پیاده سازی لیسپ کمی متفاوت است فراخوانی های زیربرنامه به صورت تودرتو است و ممکن است از پشته برای رکوردهای فعالیت استفاده شود هر رکورد فعالیت شامل یک نقطه برگشت و حافظه های موقت برای ارزیابی عبارات و انتقال پارامتر است. محیط های ارجاع محلی نیز ممکن است در همان پشته تخصیص یابند با این تفاوت که برنامه نویس اجازه دارد این وابستگی ها را دستکاری کند بنابراین معمولا در پشته جداگانه ذخیره می شوند که به صورت لیست پیوندی نمایش داده می شوند و A_list نام دارد. پشته حاوی نقاط برگشت و حافظه های موقت ممکن است از زیربرنامه نویس مخفی شود و به ترتیب تخصیص یابد پیاده سازی لیسپ مستلزم ناحیه حافظه هرم همراه با یک ناحیه ویژه و مدیر حافظه برای عناصر است که کل کلمه اشغال می کنند. هرم از طریق لیست فضای آزاد زباله روبی می شود.

زیربرنامه های بازگشتی:

در لیسپ که ساختار لیست یک ساختمان داده اولیه است بازگشتی مکانیزم کنترل مهمی برای تکرار دنباله ای از دستورات است.
دومین روش اصلی برای تعریف کنترل جریان درlisp تعاریف زیربرنامه های بازگشتی هستند. تابعی که از تعریفش بعنوان جزئی از تعریفش استفاده می کند بازگشتی نام دارد. بنابراین، یک تعریف بازگشتی، تاجایی که امکان دارد مسئله ای را به قسمتهای کوچکتر تقسیم می کند سپس این قسمتهای کوچکتر را با استفاده از توابع مشهور و جکع پاسخهای یکسان حل کرده و حل برنامه را کامل می کند. بازگشت یک روش طبیعی برای کنترل ساختارهای داده ای است که اندازه معینی ندارد. مانند لیستها،درختها و گرافها . بنابراین برای مسئله هایی که در یک فاصله از حالات دنبال حل کاندید می گردند مناسب است.
Lisp اولین زیربرنامه نویسی کاربردی بود که با روش معین تعریف تعاریف بازگشتی را پشتیبانی کرده است. ما از دو مثال کوچک برای نشان دادن بازگشت در lisp استفاده خواهیم کرد. اولین مثال برای تعیین طول یک لیست طویل دلخواه استفاده می شود. طول یک لیست برابر تعداد عناصر آن است. تابع بازگشتی آن به صورت زیر است.




(defun length (list)

(cond ((null list) 0)

(T (+ 1 (length (cdr list))))))
وقتی یک تعریف بازگشتی تعریف می شود. ما باید حالتهای اساسی را شناسایی کنیم یعنی آن قسمتهایی که نمی توانند بیشتر تجزیه شوند. مسئله اندازه وابسته به لیست است کوچکترین مسئله اندازه در لیست، لیست خالی است. بنابراین اولین چیزی که ما باید مشخص کنیم تستی برای شناسایی لیست خالی است و تعیین اینکه طول لیست خالی باید چقدر باشد تابع پیش ساخته nullتست می کند که آیا این لیست خالی است در این صورت t برمی گرداند. از آنجایی که لیست خالی بدون عنصر است تعریف می کنیم که طول لیست خالی صفر باشد کار دیگری که باید انجام شود تجزیه مسئله اندازه به قسمتهای کوچکتر است که همان مسئله می تواند برای قسمتهای کوچکتر استفاده شود . تجزیه لیست می تواند با استفاده از توابعcar,cdr انجام شود. به این معنی که ماباید تعیین کنیم تا وقتی که لیست خالی پیدا شود عنصر اول و بقیه عناصر لیست چه کار بکنند. از آنجایی که ما ازقبل لیست خالی را بعنوان حالت اساسی شناسایی کردیم، می توانیم فرض کنیم تجزیه بر روی لیستی شامل حداقل یک عنصر انجام خواهد شد. بنابراین هربار که قادر خواهیم بود تا بکاربردن cdr بقیه عناصر لیست را بدست آوریم ، ما یک عنصر اضافی پیدا کردیم که باید برای افزایش تعداد عناصر لیست قبلا شناسایی شده بوسیله یک استفاده می شود. استفاده از این تعریف تابع (()'length) بلافاصله صفر برخواهد گرداند و اگر((length '(a b c) را فراخوانی کنیم ، نتیجه 3 خواهد بود زیرا برای اینکه لیست خالی شود باید سه فراخوانی بازگشتی memberانجام دهیم بعنوان مثال دوم، تعریف بازگشتی را در نظر می گیریم که تست می کند که آیا عنصر داده شده در لیست داده شده قرار دارد اگر عنصر براستی در لیست پیدا شود زیر لیستی که با عنصر پیدا شده شروع می شود را بر می گرداند اگر عنصر پیدا نشود nil برگردانده می شود مثال فراخوانی ها هستند.

(member ’b ’(a f b d e b c)) ==> (b d e b c)


(member ’k ’(a f b d e b c)) ==> nil
مشابه تعریف بازگشتی ما لیست خالی را بعنوان حالت اساسی استفاده می کنیم برای member لیست خالی به این معنی است که عنصر مورد سوال در لیست پیدا نشود. بنابراین ما باید یک لیست را تا زمانی که عنصر مورد سوال پیدا می شود یا لیست خالی است تجزیه می کنیم تجزیه با استفاده از car,cdr انجام می شود.car برای استخراج عنصر اول لیست به کار می رود که می تواند برای کنترل اینکه با عنصر مورد سوال برابر است استفاده شود در این حالت می توانیم پردازشهای اضافی را مستقیما" متوقف کنیم اگر برابر نبود آنگاه باید تابع member را برای بقیه عناصر تا خالی شدن لیست بکار ببریم بنابراین می تواند به صورت زیر تعریف شود.

(defun member (elem list)

(cond ((null list) nil)

((equal elem (car list)) list)


(T (member elem (cdr list)))))

کنترل ترتیب اجرای برنامه – دستورات شرطی و دستورات تکرار

لیسپ بین برنامه و داده تمایز قائل نمی شود تا طراحی مفسر لیسپ ساده باشد. اجرای لیسپ در مقایسه با سایر زبانها جالب است، زیرا مفسر اصلی را می توان در لیسپ توصیف کرد. اشاره گر به تابعی که در حال اجراست به تابع apply ارسال می شود و apply تعریف آن را با استفاده از تابع دیگری به نام eval برای ارزیابی هر آرگومان ، تفسیر می کند.
مترجم لیسپ، تابع real است.real رشته کاراکتری را از فایل ورودی پایانه دریافت می کند و شناسه کامل یا ساختار لیست را در آن جستجو می کند. اگر شناسه ای پیدا شود، در ob_list جستجو می کند تا اشاره گری به آن اتم پیدا کند(اگر اتمی با آن نام پیدا نشد، اتم جدیدی ایجاد می کند). اگر ساختار لیست را بیابید که با "(" شروع می شود ، هر عنصر لیست پیمایش می شود تا به "(" برسد. هر عنصر لیست به شکل داخلی ترجمه می شود و اشاره گری به عنوان اشاره گر car در محل مناسبی درج می شود. اعداد به شکل دودویی خود ترجمه می شود و شامل توصیقگری در یک کلمه اند. اگر لیست فرعی از لیست پیدا شود که با "(" دیگری شروع گرددوread به طور بازگشتی فراخوانی می شود تا نمایش داخلی این لیست فرعی را ایجاد کند، سپس اشاره گر به این لیست فرعی به عنئان اشاره گر carعنصر بعدی لیست اصلی درج می شود. این فرایند ترجمه، برحسب اینکه لیست، تعریف تابع باشد یا لیست داده ها، فرق نمی کند . با تمام لیستها مثل هم برخورد می شود.
اجرای برنامه لیسپ شامل ارزیابی تابع لیسپ است. ترتیب اجرا با فراخوانی تابع و عبارات شرطی مشخص می شود.

ساختار شرطی . ساختار شرطی، عامل مهمی برای تصمیم گیری در برنامه است. نحو آن به صورت زیر است:


(cond masir1


2 masir


.....


masir n


(T ebarate pishfarz))



مسیر iبرابر با (predicate expression) است.cond هر predicate را به نوبت ارزیابی می کند و سپس اولین expression مربوط به predicate را که ارزش درستی دارد ارزیابی می کند. اگر تمام محصولات نادرست باشد، عبارت پیش فرض ارزیابی می شود.

ساختارif

>(if (> 4 3) 4 3)

4

>(if (< 4 3)

(- 4 3)

(- 3 4))

-1

>(if (= 4 3) t)
NIL

بانوثریا
7th August 2010, 05:03 PM
عملگرها و تقدم ترتیب عملگرها

عملگرهای موجود شامل*,+,-,=,<,<=,>=
در لیسپ تقدم عملگرها از چپ به راست می باشد.

<, >, <=, >=

Format: (< <num1> <num2> ... ) (> <num1> <num2> ... ) (<= <num1>

<num2> ... ) (>= <num1> <num2> ... )

_

Examples:

>(< 2 67)

T

>(< 67 2)

NIL

>(> 67 2)

T

>(< 3 6 9)

T

>(< 4)

T

>(< 2 2 6)

NIL

>(<= 2 2 6)

T

>(>= 2 2 6)

NIL

>(< 6/2 3.0)

NIL






=

Format: (= <num1> <num2> ...)

Examples:

>(= 2)

T

>(= 2 3)

NIL

>(= 2 3 4)

NIL

>(= 2 2 2 2 )

T

>(= 2 2 3 2)

NIL

>(= 2 'a)








Error: A is not of type NUMBER.











مدیریت حافظه – ایستا یا پویا – مشکلات مدیریت حافظه

در لیسپ حافظه به طور ضمنی تخصیص می یابد در این موارد برنامه نیاز به حافظه هرم دارد که بلوک هایی از حافظه را به طور پویا تخصیص می دهد و آزاد می کند.
لیسپ لیست فضای آزاد و جمع آوری زباله ها را به عنوان مبنایی برای مدیریت حافظه قرار میدهد.
سومین نوع مدیریت حافظه مدیریت حافظه هرم نام دارد هرم بلوکی از حافظه است که در آن قطعاتی از حافظه به روش غیر ساخت یافته تخصیص می یابند و آزاد می شوند. وقتی به حافظه هرم نیاز می شود که در زمان اجرا در هر نقطه از برنامه بتوان حافظه ای را تخصیص داد و آزاد کرد مثل ایجاد و حذف یا بسط ساختمان داده های تعریف شده توسط کاربر در هر نقطه ای از برنامه. در لیسپ در نقطه ای از برنامه می توان عنصر جدیدی را به ساختار لیست موجود اضافه کرد و نیاز به تخصیص حافظه است در لیسپ حافظه می تواند در هر نقطه ای از برنامه آزاد شود.
لیسپ دارای مدیریت حافظه پویاست.


















امکانات ویژه زبان و ساختارهای جدید در آن




second, third, etc. (FUNCTIONS)

Format: (second <list>) (third <list>) etc

Examples:

>(second '(1 2 3 4))

2

>(fourth '(1 2 3 4))

4

>(ninth '(1 2 3 4))

NIL






reverse (FUNCTION)

Format: (reverse <list>)

K

Examples:

>(reverse '(picard riker worf crusher))

(CRUSHER WORF RIKER PICARD)

>(reverse (reverse '(picard riker worf crusher)))

(PICARD RIKER WORF CRUSHER)

>(reverse '((this list) (of words)))

((OF WORDS) (THIS LIST))






max, min (FUNCTIONS)

Format: (max <num1> ... <numN>) (min <num1> ... <numN>)

Examples:

>(max 1 4 3 15 (* 9 2))

18

>(min 3 4 (- 7 19) 5 6.0)

-12

>(max 3)

3

>(min 4)

4






mapcar (FUNCTION)

Format: (mapcar <func> <lis1> . . . <lisN>)

Examples:

>(mapcar '+ '(1 2 3))

(1 2 3)

>(mapcar '+ '(1 2 3) '(4 5 6))

(5 7 9)

>(mapcar '+ '(1 2 3) '(4 5 6) '(7 8 9))

(12 15 18)

>(mapcar '+ '(1 2) '(3 4 5))

(4 6)

>(mapcar '< '(1 2 3) '(4 5 0))

(T T NIL)

>(mapcar '< '(1 2 3) '(4 5))

(T T)






first (FUNCTION)

Format: (first <exp>)

Examples:

> (first '(1 2 3))

1

> (first '((a (b (c)) d) e (f)))

(A (B (C)) D)

> (first ())

NIL

> (first 'a)

Error: A is not of type LIST






evenp, oddp (PREDICATES)

Format: (evenp <num>) (oddp <num>)

Examples:

>(oddp 3)

T

>(oddp 68)

NIL

>(evenp 4.0)

Error: 4.0 is not of type INTEGER.






eql, equal (PREDICATE)

Format: (eql <exp1> <exp2>)

Examples:

> (eql 'hello 'hello)

T

> (eql -19 -19)

T

> (eql 2 3)

NIL

> (eql '(1 2 3) '(1 2 3))

NIL

L

> (setq a '(1 2 3))

(1 2 3)

> (setq b '(1 2 3))

(1 2 3)

> (eql a b)

NIL

> (setq c a)

(1 2 3)

> (eql a c)

T

> (eql b c)

NIL

Format: (equal <exp1> <exp2>)

Examples:

> (equal 'hey 'hello)

NIL

> (equal -81 -81)

T

> (equal '(1 (2 3)) '(1 (2 3)))

T

> (setq a '(1 2 3))

(1 2 3)

> (setq b '(1 2 3))

(1 2 3)

> (equal a b)

T

> (setq c a)

(1 2 3)

> (equal a c)

T






butlast (FUNCTION)

Format: (butlast <list>) (butlast <list> <int>)

Examples:

>(butlast '(a s d f))

(A S D)

>(butlast '(a s d f) 2)

(A S)

>(butlast '(a s d f) 0)

(A S D F)






1+, 1- (FUNCTIONS)

Q

Format: (1+ <num>) (1- <num>)

Examples:

>(1+ 3)

4

>(1- pi)

2.1415926535897931

>(1+ (1- 3))


3

kartal_2757
18th November 2010, 12:00 AM
کدام زبانها دارای انقیاد زود رس وکدام زبانها دارای انقیاد دیر رس میباشند،(بغیر از زبانهای c ,c+,c++,vb,پاسکال)[soal]

fat321
9th March 2011, 05:09 AM
با سلام
منظور از تفسیر ماشین خودکار چیست؟ اینکه مجموعه ای از نمادها با نمادهای دیگر جابه جا میشوند به چه معناست؟ ممکن است خواهش کنم با مثال توضیح دهید؟
ممنونم

assembeler
20th April 2011, 09:09 PM
لیسپ لیسپ یک زبان برنامه‌نویسی رایانه (http://fa.wikipedia.org/wiki/%D8%B1%D8%A7%DB%8C%D8%A7%D9%86%D9%87) است که در سال ۱۹۵۸ به وسیلهٔ جان مک‌کارتی (http://fa.wikipedia.org/wiki/%D8%AC%D8%A7%D9%86_%D9%85%DA%A9%E2%80%8C%DA%A9%D8% A7%D8%B1%D8%AA%DB%8C) ابداع شده‌است. این زبان، مانند زبان برنامه‌نویسی پرولوگ، بیشتر برای برنامه‌نویسی هوش مصنوعی (http://fa.wikipedia.org/wiki/%D9%87%D9%88%D8%B4_%D9%85%D8%B5%D9%86%D9%88%D8%B9% DB%8C) مورد استفاده قرار می‌گیرد. با توجه به اینکه زبان لیسپ از نحو ساده‌ای برخوردار است، تجزیه و پیاده‌سازی آن نسبتاً با سهولت انجام می‌شود.
متن برنامه‌های لیسپ عموماً از نمادها و لیست‌هایی از نمادها تشکیل می‌شود و بدین خاطر است که این زبان لیسپ (مخفف پردازش لیست) نامیده شده‌است. یکی از ویژگی‌های جالب زبان لیسپ این است که خود برنامه‌های لیسپ نیز لیست هستند و بنا بر این، می‌توان با برنامه‌ها به عنوان داده‌ها رفتار کرد و یا داده‌ها را به عنوان برنامه ارزیابی نمود.
لیسپ دارای گویش‌های مختلفی است که بعضی از آنها دارای قابلیت‌های شیءگرا نیز هستند. از این میان می‌توان به کامن لیسپ اشاره کرد.
در ابتدا لیسپ به عنوان علامتگذاری و نمادسازی ریاضیات و برای برنامه‌های کامپیوتری ابداع شد.زبان لیسپ به سرعت مورد توجه برنامه نویسان از جمله برای تحقیقات علمی هوش مصنوعی قرار گرفت.لیسپ یکی از ابتدائی ز بان‌های برنامه نویسی می‌باشد،ودر علوم کامپیوتر بر بسیاری از تفکرات و ایده‌ها پیشگام بود.لیسپ شامل ساختمان دادهٔ درخت،مدریت نگهداری اتوماتیک،برنامه نویسی پویا،برنامه نویسی شی گرا و کامپایلر مستقل می‌باشد.
نام لیسپ از زبان پردازش لیسپ گرفته شده‌است.لینک لیست یکی از قسمت‌های اصلی ساختمان دادهٔ زبان لیسپ است و سورس کد لیسپ از لیست‌ها ساخته شده‌است و می‌تواند به عنوان ساختمان داده عمل کند.پیشرفت و توسعهٔ سیستم ماکرو به برنامه نویسان اجازه می‌دهد تا ترکیب‌های جدید ویا حتی حیطهٔ زبان‌های برنامه نویسی ویژه‌ای را ایجاد کرده و در زبان لیسپ تعبیه کنند. قابلیت تبادل کدها و داده‌ها به زبان لیسپ قابلیت تشخیص ترکیب‌ها را می‌دهد،همهٔ کدهای برنامه به صورت عبارت‌های نمادین یا لیست‌های پرانتز گذاری شده نوشته شده‌اند.
یک تابع می‌تواند توسط خودش ویا توابع دیگر فراخوانی شود ویا طبق قواعد نحوی نوشتن یک لیست و استفاده از اول نام عملگرها و پیروی کردن از قواعد آرگومان‌ها ایجاد شود.به عنوان مثال تابع fدارای 3 آرگومان می‌باشد و به صورت مقابل توانائی فراخوانی را دارد و مورد استفاده قرار می‌گیرد:

(f x y z)
زبان برنامه نویسی لیسپ توسط جان مک کارتی در سال 1958 در حالی که در مؤسسهٔ فناوری ماساچوست (MIT) بود ابداع شد.مک کارتی طرح خودش را در یک مقالهٔ مرتبط با انجمن ماشین آلات کامپیوتری در سال 1960 منتشر کرد.طرح وی در ابتدا به صورت «بخش اول:توابع بازگشتی از دید عبارت‌های نمادین و محاسبهٔ آنها توسط ماشین» ارائه شد و بخش دوم آن هیچگاه منتشر نشد.وی نشان داد که با یک تعداد ساده و کمی از عملگرها و علمتگذاری توابع می‌توان یک زبان تورینگ کامل برای الگوریتم‌ها ایجاد کرد. زبان پردازش اطلاعات اولین زبان هوش مصنوعی بود. از سال 1955 یا 1956 و پیش از آن ایده‌های بسیاری بر زبان لیسپ وارد شد از جمله پردازش لیست و توابع بازگشتی که در زبان لیسپ به کار برده شد. ثبت‌های اصلی مک کارتی به صورت عبارت‌های غیر نمادین که خواستار تفسیر کردن و برگرداندن به عبارت‌های نمادین بود.به عنوان مثال عبارت غیر نمادین car[consA,B (http://fa.wikipedia.org/w/index.php?title=A,B&action=edit&redlink=1) معادل عبارت نمادین (car (cons A B)بود که در زبان لیسپ به کار گرفته شده بود.برنامه نویسان به سرعت عبارت نمادین را انتخاب و عبارت‌های غیر نمادین را ترک کردند.
لیسپ برای اولین بار توسط استفان راسل روی یک کامپیوتر IBM 704 اجرا شد. راسل مقالهٔ مک کارسی را مطالعه کرد و دریافت که توابع لیسپ می‌توانند در کد ماشین اجرا شوند. این نتیجه از مطالعه و دریافت راسل نشان می‌دهد که مفسر لیسپ می‌توانست برای اجرای برنامه‌های لیسپ و ارزیابی صحیح عبارت لیسپ استفاده شود.
دو زبان اسمبلی به عنوان دو عملیات اصلی و ابتدائی تجزیه و جدا کردن عناصر اصلی لیست برای IBM 704 شد.این دو زبان اسمبلی car (مضمون آدرس ثبات) و cdr (محتوای کاهش میزان ثبات‌ها) نسخهٔ لیسپ هنوز ازcar وcdr برای عملیاتی که اولین عنصر در یک لیست و باقی ماندهٔ لیست را برمی‌گرداند،استفاده می‌کند.
اولین کامپایلر تکمیل شدهٔ لیسپ،در سال 1962توسط تام هارت و مایک لوین در MIT اجرا شد، این کامپالر معرفی شده مدل لیسپ با کامپایلر نحوی در هر کامپایل و ترجمهٔ توابع می‌تواند به طور رایگان در هم بیامیزد.
زبان به کار گرفته شده در ثبت هارت و لوین نسبت به کدهای ابتدائی مک کارتی به شیوهٔ لیسپ مدرن و جدید نزدیک تر می‌باشد.
پیوستن به هوش مصنوعی:
بعد از شروع لیسپ ، لیسپ به انجمن تحقیقاتی هوش مصنوعی پیوست ، خصوصا به سیستم‌های PDP ، زبان لیسپ به عنوان پیاده ساز طرح کوچک زبان برنامه نویسی استفاده می‌شود که مبنایی برای سیستم معروف هوش مصنوعی SHRLU بود.
در سال 1970 تحقیقات علمی هوش مصنوعی به شاخه‌های تجاری انشعاب پیدا کرد که کارایی سیستم لیسپ موجود در این زمینه یک روند رو به رشد شد.
لیسپ یک سیستم مشکل برای اجرا، مهارت کامپایلر و سخت افزار ذخیره کننده را در سال 1970 دارا باشد. بازیابی عادی حافظه ، توسط دانشجوی فارغالتحصیل MIT ( دانیل ادوارد ) گسترش داده شده ،که برای اجرای لیسپ روی سیستم‌های محاساتی ساخته شده بود اما راندمان آن هنوز یک مشکل بود. برای رهبری ماشین لیسپ: سخت افزار اختصاصی برای اجرای محیط لیسپ و برنامه‌های آن استفاده می‌شود. پیشروی در هردو سخت افزار کامپیوتر و فناوری کامپایلر از ماشین‌های لیسپ از کار افتاده الهام گرفته شده‌است.
طی شک کوشش بزرگ نسخه‌های بیشماری از زبان لیسپ را در یک زبان واحد متمرکز و متحد کردند(نسخه‌های برجسته و قابل ملاحظه‌ای شامل: اینترلیسپ ، مک لیسپ ، متالیسپ ، و فرانزلیسپ) زبان‌های جدید (لیسپ عمومی و مشترک ) در اصل یک زیر مجموعهٔ سازگاری از نسخه‌های تعویض شده بود. در سال 1994 ، ANSI یک لیسپ عمومی و مشترک استاندارد منتشر کرد. لیسپ عمومی و مشترک زبان برنامه نویسی فناوری اطلاعات ANSI X3.226-1994 در آن زمان فروشگاه‌های جهانی برای لیسپ خیلی کوچکتر از المان بود.
ترکیب و معنا شناسی:
لیسپ یک عبارت جهتدار است ، برخلاف بیشتر زبان‌های دیگر ، بین عبارت‌ها و جمله‌ها تمایز و فرقی وجود ندارد . همهٔ کدها و داده‌ها به عنوان عبارت‌ها نوشته شده‌اند – زمانی که یک عبارت ارزیابی می‌شود یک مقدار ( یا یک لیستی از مقادیر) را می‌سازد ، که آن هم در داخل عبارات دیگر جاسازی می‌شود.
مقالهٔ 1958 مک کارتی دو نوع از ترکیب‌ها را معرفی کرد: عبارت نمادین ***ps هم نامیده می‌شود ، که بازتابی از نمایش داخلی کدها و داده هاست و عبارت غیر نمادین هرگز مورد توجه قرار نگرفت و تقریبا همهٔ زبان‌ها امروزه از عبارات نمادین استفاده می‌کنند.
استفاده از پرانتزگذاری‌ها تفاوت بسیار آشکار و مشهودی میان لیسپ و دیگر زبان‌های برنامه نویسی ایجاد کرده‌است . اسم مستعار LISP از Lost In Stupid Parenthese و یا Lost of Irritating Supper fluous parenthese گرفته شده‌است . هرچند ترکیب عبارت‌های نمادین مسئولی برای توان لیسپ است ، این ترکیب به شدت با قاعده و منظم است.
هرچند ترکیبات لیسپ به نمادگذاری قدیمی محدود نشده‌اند می‌تواند به سبک‌های دیگر توسعه پیدا کند. تکیه روی عبارت‌ها ، قابلیت انعطاف پذیری زیادی به زبان می‌دهد ، زیرا توابع لیسپ به صورت لیست نوشته شده‌اند ، آنها دقیقا مانند داده‌ها می‌توانند پردازش شوند، این قابلیت اجازه می‌دهد برنامه‌های لیسپ به سادگی و راحتی نوشته شوند و به نسبت برنامه‌های دیگر به راحتی اداره شوند . (برنامه نویسی غیر نمادین)بسیاری از نسخه‌های زبان لیسپ با عناصر جدا شده توسط فاصله‌های سفید و پرانتزگذاری شده‌ها نوشته می‌شود. برای مثال (1 2 f00 ) یک لیست است که عنصرهای آن سه اتم هستند ( اتم: کوچکترین عضو لیست ) : این مقادیر 1 و 2 و F00 هستند. این مقادیر ضمنا دارای نوع داده‌ای خاصی هستند ، مثلا این لیست دارای دو عدد صحیح 1 و 2 و یک نوع دادهٔ ویژهٔ لیسپ که یک Symbol یا نماد نامیده می‌شود.
همچنین یک لیست خالی () به عنوان یک اتم ویژهٔ صفر و یا پوچ معرفی شده‌است. موجودیت یک لیسپ از اتم و لیست تشکیل می‌شود. عبات‌ها به عنوان لیست نوشته شده‌اند ، استفاده کردن از ثبت‌های پیشوندی ، عناصر ابتدایی در لیست نامی از یک شکل تابع ، عملگرها ، ماکروها و یا اپراتورهای ویژه‌است.
آرگومان‌ها باقیمانده‌هایی از لیست‌ها هستند ، برای مثال تابع list آرگومان‌ها را به عنوان یک لیست بر می‌گرداند ، بنابراین عبارت (list ‘1 ‘2 ‘foo) ارزیابی می‌شود و حاصل این ارزیابی لیست (1,2,foo) می‌باشد.
نیازی به ارزیابی کردن اعداد نیست چون ارزیابی عدد 1 عدد 1 می‌شود.آرگومان‌های مثال قبل از اعداد هستند یعنی آرگومان‌های ویژه که این آرگومان‌ها از ارزیابی کردن آرگومان‌ها جلوگیری می‌کنند چون مقادیر آن‌ها مشخص است.هر عبارتی که بیان می‌شود قبل از اینکه با عبارات دیگر پیوست داده شود به صورت بازگشتی ارزیابی می‌شود.
(list(1 2 (list(3 4)))) در این مثال حاصل اررزیابی به صورت لیست (1,2(3,4)) می‌باشد ،توجه کنید این لیست دارای 3 آرگومان می‌باشد ، لیست‌ها می‌توانند به صورت تو در تو باشند . اپراتورهای حسابگر به صورت همسان رفتار می‌کنند.
حاصل عبارت (+1 2 3 4 ) عدد 10 می‌باشد. عبارت معادل عبارت بالا به صورت 1+2+3+4 می‌باشد که از نشانگذاری میان وندی استفاد شده‌است. اپراتورهای حسابگر در زبان لیسپ variadic(n-ary) که زبان لیسپ توانایی پذیرفتن هر تعداد آرگومان را داراست.
عملگرهای ویژه ساختمان کنترل لیسپ را آماده می‌کنند. برای مثال ، اپراتور ویژه if سه آرگومان می‌پذیرد،اگر اولین آرگومان صفر و یا خالی باشد دومین آرگومان ارزیابی می‌شود و در غیر این صورت هٔرگومان سوم بررسی می‌شود . بنابر این if(nill(list 1 2 “foo”)(list 3 4 “bar”) که تنها آرگومان (list 3 4 “bar”) بررسی می‌شود.
عبارت‌های لاندا(Lambda) :
دیگر عبارت‌های ویژه لاندا می‌باشد که برای وصل کردن متغیرها به مقادیرشان که درون یک عبارت ارزیابی می‌شوند استفاده می‌شود. این عملگر همچنین برای ایجاد کردن توابع هم استفاده می‌شود. آرگومان‌های درون لاندا یک لیستی از آرگومان‌ها هستند و عبارت ارزیابی توابع می‌باشند. مقادیر بازگشتی مقادیری از عبارت قبلی که ارزیابی شده‌اند هستند.
عبارت (Lambda(arg)(+arg1)) زمانی که این تابع به کار برده می‌شود به صورت یک تابع ارزیابی می‌شود و وظیفهٔ این تابع معرفی کردن یک آرگومان و اتصال دادن آرگومان به arg و در نهایت برگرداندن یک عدد بزرگتر از آرگومان قبلی می‌باشد عبارت‌های لاندا خیلی متفاوت با نام تابع رفتار نمی‌کند بنابراین اگر در عبارت (Lambda(arg)(+arg1))5->6 عدد 5 را وارد کنیم خروجی آن 6 می‌شود. اتم‌ها : در نسخهٔ اصلی لیسپ دو نوع دادهٔ ابتدایی وجود دارد: اتم‌ها و لیست‌ها یک لیست یک رشتهٔ منظم و محدودی از عناصر می‌باشد ، که هر عنصر در درون خودش یکی از این اتم‌ها و یا لیست‌ها را دارد و یک اتم یک عدد یا یک نماد می‌باشد.
در اصل یک نماد یک رقم منحصر به فرد می‌باشدو به عنوان یک رشتهٔ عددی در سورس کد نوشته شده و هر دو به عنوان یک نام متغیر و یک رقم داده‌ای در پردازش نمادین استفاده می‌شود برای مثال list(foo(BAR 1)2) شامل سه عنصر : Symbol foo و list(BAR 1) و عدد 2 می‌باشد. تفاوت اصلی بین اتم‌ها و لیست‌ها این است که اتم‌ها تغییر ناپذیر و منحصر به فرد می‌باشند. دو اتم که دقیقا به یک صورت و به یک روش در یک شی نوشته شده باشد در مکان متفاوتی در سورس کد ظاهر می‌شوند، هر لیست یک شی مجزا می‌باشد و به خاطر اینکه مستقل از دیگر لیست هاست و از دیگر لیست‌ها به وسیلهٔ مقایسهٔ عملگرها مشخص می‌شود.
Cons‌ها و لیست‌ها:
یک لیست لیسپ یک لینک لیست جداست، هر ذره از این لیست یک Cons نامیده می‌شود و از دو اشاره گر که Car و Cdr نامیده می‌شوند ترکیب شده‌است این دو اشاره گر به ترتیب معادل دو فیلد Data و Next در مقالهٔ لینک لیست می‌باشد.
Car -> Data Cdr -> Next
بسیاری از ساختمان داده‌ها می‌توانند ترکیب‌هایی از خانه‌های Cons را داشت باشند ، یکی از این ساختمان داده‌های ابتدایی لیست مخصوص نامیده می‌شود ، یک لیست مخصوص هر دو نماد لیست خالی nill و یا خانه‌ها Cons را داراستکه در هر یک از این خانه‌ها هر اشاره گر Car به یک داده اشاره می‌کند (که ممکن است این اشاره گر Cons به یک لیست اشاره کند) و یک اشاره گر Cdr به یک لیست مخصوص دیگر اشاره می‌کند. اگر یک Cons داده به سر یک لینک لیست برده شود سپس اشاره گر Car آن به اولین عنصر از لیست و اشاره گر Cdr آن به انتهای یک لیست اشاره می‌کند به همین دلیل عملکرد Car و Cdr را به ترتیب first و rest هم نامیده می‌شود.
ارایهٔ لیست عبارت نمادین:
نمایش پرانتزگذلری عبارت نمادین ساختمان لینک لیست . چندین راه برای نمایش لیست یکسان به عنوان یک عبارت نمادین وجود دارد . یک خانه (Cons ) می‌تواند به صورت نشان گذاری جفت نقطه گذاری شده نوشته شود به عنوان مثال (a.b) که در آن a یک Car و b یک Cdr است. یک لیست مخصوص بلند ممکن است به صورت یک نشان گذاری جفت نقطه گذاری شده نوشته شود .(a.(b.(c.(d.nill))))
طبق قرارداد کوتاه شدهٔ عبارت بالا به صورت (a b c d ) در نمادسازی لیست می‌باشد یک لیست مخصوص ممکن است در یک ترکیبی از دو صورت (a b c.d) نوشته شود . برای سیستمی از سه Cons که آخرین Cdr آن d است.
دستورالعمل‌های پردازش لیست:
لیسپ دستورالعمل‌های زیادی را برای دستیابی و کنترل لیست‌ها فراهم می‌کند . لیست‌ها می‌توانند مستقیما با پردازهٔ لیست ایجاد شوند .لیست هر تعدادی از آرگومان‌ها را می‌پذیرد و تعدادی از آرگومان‌ها را بر می‌گرداند.
(list 1 2 ‘a 3 ); Output : (1 2 a 3 ) (list 1 ‘(2 3) 4 ); Output : (1 (2 3) 4)
به این دلیل راهی که لیست‌ها ایجادمی شوند از جفت‌های Cons (Car,Cdr) پردازهٔ Cons می‌تواند برای اضافه کردن یک عنصر به جلوی یک لیست استفاده شود. توجه کنید که پردازهٔ Cons در هدایت و به کار بردن آرگومان‌های لیست نامتقارن است ، بدین دلیل روش‌های لیست‌ها ایجاد می‌شوند.
(Cons 1 ‘(2 3)); Output: (1 2 3 ) (Cons ’(1 2) ‘(3 4)) Output : ((1 2) 3 4)
پردازهٔ Oppend دو یا چند لیست را با هم ادغام می‌کند و یک لیست واحد ایجاد می‌کند زیرا لیست لیسپ یک لینک لیست است و پیچیدگی زمانی الحاق کردن لیست‌ها از مرتبهٔ پیچیدگی زمانی O(n) می‌باشد.
ساختار اشتراکی: لیست‌های لیسپ لینک لیست‌های ساده می‌توانند با یکی دیگر از لیست‌ها در ساختمان مشترک باشند به عبارت دیگر دو لیست می‌توانند دم یکسانی داشته باشندیا رشتهٔ پایانی از Cons‌های یکسانی داشته باشند مثلا:
(setf foo (list 'a 'b 'c)) (setf bar (cons 'x (cdr foo)))
لیست foo و bar به ترتیب به صورت (a b c) و (X b c ) هستند هرچند دم (b c ) در هر دو لیست ساختار یکسانی دارند ولی مانند هم نیستند، خانه‌های Cons اشاره گر به b و c در محل حافظهٔ یکسانی برای هردو لیست قرار دارد.
ساختار اشتراکی سریع تر از کپی کردن می‌تواند به صورت چشمگیری کارایی را بهبود بخشند. هرچند ، این مهارت می‌تواند متقابلا در راه‌های نامطلوب با عملکردهایی که تغییرات لیست‌های گذشته روی آرگومان‌های آن تاثیر بگذارد ، اثر کند.
تغییرات یک لیست از قبیل تغییر دادن C با یک goose روی دیگری نیز تاثیر می‌گذارد setf (third foo) 'goose) که این تغییر نتیجه را به صورت (a b goose) تغییر می‌دهد اما bar هم تغییر می‌کند (X b goose) که ممکن است یک نتیجهٔ غیر منتظره باشد.
زبان‌های برنامه نویسی Lisp معمولا از یک خط دستور محاوره‌ای استفاده می‌کنند،که می‌تواند با یک محیط پیچیدهٔ گسترش یافته ترکیب شود.کاربر اصطلاحات و دستورات را در خط دستور وارد کرده یا با رهبری IDE آنها را به سیستم Lisp می‌فرستد. Lisp دستورات را می‌خواند ، آن‌ها را ارزیابی می‌کند و نتایج را چاپ می‌کند. به این دلیل است که خط دستور زبان Lisp به حلقهٔ Read-Eval-Print یا REPL معروف است.
نمونهٔ ساده‌ای از عملیات REPL در زیر آمده‌است. این یک شرح ساده‌است که بسیاری از المان‌های Lispواقعی در آن نمی‌آید مانند ماکروها و کوئت‌ها.
تابع read جملات متنی را به عنوان ورودی می‌پذیرد و آنها را به ساختار لیست تجزیه می‌کند. به عنوان مثال ، وقتی شما رشتهٔ (+ 1 2) را در اعلان تایپ می‌کنید، تابع read آن را به یک لیست پیوندی حاصل از 3 المان ترجمه می‌کند: علامت + ، عدد 1 و عدد 2 . خیلی اتفاق می‌افتد که لیست قسمت موثری از یک کد Lisp باشد که قابل ارزیابی است.به همین دلیل است که یک قطار از لیست به یک تابع نام عملگر مع می‌دهد.
تابع eval ساختار لیست را ارزیابی می‌کند و نوعی دیگر از ساختار را به عنوان نتیجه باز می‌گرداند.ارزیابی کردن لزوما تفسیر کردن معنی نمی‌دهد؛ بعضی سیستم‌های Lisp هر عبارتی را به زبان ماشین تبدیل می‌کنند. خیلی ساده است؛ به هر حال؛ برای تعریف ارزیابی به عنوان تفسیر : برای ارزیابی یک لیست که نام تابع دارد ، eval ابتدا تمام آرگومان‌های داده شده به cdr اش را ارزیابی می‌کند و سپس تابع را روی آن آرگومان‌ها اعمال می‌کند.در این مثال ، تابع عمل جمع است و به آرگومان‌های (1 2) اعمال می‌شود که نتیجه 3 است.این نتیجهٔ ارزیابی است.
این وظیفهٔ تابع print است که نتیجه را به کاربر نمایش دهد. برای نتیجهٔ سادهٔ 3 این کار ناقابل است. یک عبارت که با قسمتی از ساختار لیست ارزیابی می‌شود میاز دارد که print لیست را به حرکت در آورد و در خروجی به شکل یک عبارت S نمایش دهد.
برای اجرا کردن یک REPL در Lisp ، تنها لازم است که این سه تابع را اجرا کنید و یک تابع حلقه بی نهایت را.(به طور طبیعی اجرای eval پس از اجرای عملگرهای ویژه‌ای مانند if پیچیده خواهد شد.)یک REPL ساده به خودی خود با یک خط کد انجام شد: (loop(print(eval(red))))
لیست در اصل تعداد کمی ساختار کنترلی دارد. منتها در تکامل و گسترش زبان تعداد زیادی به آن اضافه شدند.(عملگر اصلی شرایط در زبان Lisp که cond بود بعدا متشکل شد از ساختار if-then-else )
برنامه نویسان در نسخهٔ Scheme حلقه‌ها را به صورت بازگشت دم( tail recursion ) بیان می‌کنند. موسسات متعارف علوم کامپیوتر Scheme بعضی دانشجویان را متعاقد می‌کند که تنها راه تکرار در زبان Lisp استفاده از بازگشت دم است؛ این اشتباه است. تمامی نسخه‌های متداول دیده شده از Lisp دارای ساختارهای الزامی برای تکرار هستند.درScheme دستور do به عنوان دستور حلقه پیچیدهٔ Lisp است. علاوه بر این مسالهٔ اصلی که شی گرایی را مهمتر از مسالهٔ فاعلی کرده این است که Scheme نیازهای ویژه‌ای برای کارکردن با فراخوانی دم(tail calls )دارد، در نتیجه دلیل ترغیب Scheme به استفاده از بازگشت دم این است که روش صراحتا با تعریف خود زبان پشتیبانی می‌شود . در مقابل ، ANSI Common Lisp نیازی به بهینه سازی که معمولا به حذف فراخوانی دم گفته می‌شود ندارد. در نتیجه این حقیقت که بازگشت دم به عنوان یک جایگزین تصادفی برای استفاده از ساختارهای مبتنی بر تکرار ( مانند do dolist loop ) توصیه نمی‌شود تنها یک مسالهٔ برتری ادبی نیست ، ولی بالقوه یکی از کارآمدهاست ( بعد از این که این روش فقط به عنوان یک پرش ساده به کار نرفت) و به عنوان یک تصحیح برنامه‌است .
بعضی از ساختارهای کنترلی Lisp عملگرهای ویژه‌ای هستند ، هم ارز کلیدواژه‌های ترکیبی باقی زبان‌ها. عباراتی که این عملگرها استفاده می‌کنند ظاهری شبیه فراخوانی تابع دارد، تفاوت اینجاست که آرگومان‌ها ضرورتا نباید ارزیابی شوند یا در مورد تکرار شاید بارها ارزیابی شوند. در مقابل اکثر زبان‌های برنامه نویسی ، Lisp به برنامه نویسان اجازه می‌دهد با خود زبان ساختاهای کنترلی را پیاده سازی کنند.ساختارهای کنترلی زیادی در ماکروهای Lisp پیاده سازی می‌شوند و برنامه نویسان می‌توانند هر ماکرو را گسترش دهند ،برای آنانی که می‌خواهند بدانند چطور کار می‌کند.
هر دوی Lisp Commonو Scheme دارای عملگرهای کنترلی غیر محلی هستند.تفاوت این عملگرها یکی از عمیق ترین تفاوت‌ها مابین این دو نسخهٔ زبان است. Scheme از ورودی مستمر با استفاده از روش call/cc پشتیبانی می‌کند ، که به برنامه اجازهٔ ذخیره ( و بعدا بازیابی کردن) یک عملیات ویژه را می‌دهد . Common Lisp از ورودی مستمر پشتیبانی نمی‌کند ولی از راه‌های زیادی برای انجام رهایی از تکرار پشتیبانی می‌کند.

منبع

· Patrick Winston and Berthold Horn, Lisp, Addison Wesley; 3 edition (January 1, 1989), ISBN 0-201-08319-1 (http://fa.wikipedia.org/wiki/%D9%88%DB%8C%DA%98%D9%87:%D9%85%D9%86%D8%A7%D8%A8% D8%B9_%DA%A9%D8%AA%D8%A7%D8%A8/0201083191)

استفاده از تمامی مطالب سایت تنها با ذکر منبع آن به نام سایت علمی نخبگان جوان و ذکر آدرس سایت مجاز است

استفاده از نام و برند نخبگان جوان به هر نحو توسط سایر سایت ها ممنوع بوده و پیگرد قانونی دارد