لیسپ معمولی کیست؟ توضیح بده.
لیسپ معمولی، که معمولاً به صورت CL مخفف می‌شود، یک نوع از لیسپ است که به وسیلهٔ ANSI *۳۰۲۶۶–۱۹۹۴ استاندارد شده و برای استاندارد کردن نسخه‌های منشعب شدهٔ لیسپ که بخش‌هایی از آن را دارا هستند، گسترش یافته‌است. CL در واقع یک پیاده‌سازی نیست بلکه یک مشخصهٔ زبانی است که پیاده‌سازی‌های لیسپ با آن مطابقت دارد.لیسپ معمولی یک زبان برنامه‌نویسی همه منظوره‌است، در مقایسه با نسخه‌های لیسپ مانند لیسپ ایمکس و آتولیسپ که زبان‌های جامع جاسازی شده در تولیدات ویژه هستند. برخلاف بسیاری از لیسپ‌های اولیه، لیسپ معمولی مانند Scheme از حوزه لغوی برای متغیرها استفاده می‌کند.لیسپ معمولی یک زبان برنامه‌نویسی چندمدلی است که:نحو.لیسپ معمولی از عبارات نحوی برای دلالت بر کد و ساختمان داده استفاده می‌کند. فراخوانی‌های ماکرو و تابع به صورت لیستی با آوردن نام تابع در ابتدا نوشته شده‌است، مانند مثال زیر:۲ و ۲ را جمع می‌کند و نتیجه ۴ می‌دهد: (+ 2 2)به متغیر "p" مقدار ۳٫۱۴۱۵ می‌دهد: (setf *p* 3.1415)تعریف یک تابع که مجذور یک عدد را حساب می‌کند: (defun square (x) (* x x))اجرای تابع که عدد ۹ را برمی‌گرداند: (square 3)انواع داده.لیسپ معمولی انواع داده‌ای زیادی حتی بیشتر از بسیاری زبان‌ها دارد.انواع اسکالر.انواع عدد شامل اعداد صحیح، کسری، ممیز شناور و اعداد مختلط می‌باشد. لیسپ معمولی از bignums برای نشان دادن مقدارهای عددی با دقت و اندازه دلخواه استفاده می‌کند. نوع کسری، کسرها را با دقت نشان می‌دهد، این ویژگی در بسیاری از زبان‌ها وجود ندارد. لیسپ معمولی به صورت اتوماتیک مقدارهای عددی را بین این داده‌ها به صورت مناسب وارد می‌کند.نوع کاراکتر لیسپ معمولی به کاراکترهای ASCII محدود نمی‌شود- تعجب‌آور نیست وقتی لیسپ، ASCII را نیز شامل می‌شود. بعضی از پیاده‌سازی‌های مدرن به کاراکترهای یونی کد نیز اجازه استفاده می‌دهد.نوع سمبل نیز در زبان‌های لیسپ رایج است، اما عموماً خارج از آن‌ها شناخته شده نیست. یک سمبل یک شی داده‌ای نامدار واحد است. سمبل‌ها در لیسپ شبیه شناسه‌ها در زبان‌های دیگر هستند، که به عنوان متغیرها برای نگهداری ارزش‌ها استفاده می‌شوند. اگرچه، آن‌ها بسیار عمومی تر هستند و می‌توانند برای خودشان هم استفاده شوند. معمولاً وقتی یک سمبل ارزیابی می‌شود، مقدارش به عنوان یک متغیر برگردانده می‌شود. استثناهایی نیز وجود دارد: سمبل‌های کلمات کلیدی مثل: foo با خودشان ارزیابی می‌شوند و مقدارهای بولی در لیسپ معمولی به وسیلهٔ سمبل‌های رزرو شدهٔ T و NIL نشان داده می‌شوند.ساختمان‌های داده.انواع ترتیبی در لیسپ معمولی شامل لیست‌ها، بردارها، بردارهای بیتی و رشته‌ها می‌باشد. مانند لیسپ‌های دیگر، لیست‌ها در لیسپ معمولی از consها ساختمان داده با دو بخش است که car وcdr نامیده می‌شود. یک لیست یک زنجیره پیوندی از cons هاست؛ که car مربوط به cons به عضوی از یک لیست ارجاع می‌کند (احتمالاً لیست دیگر). هر cdr مربوط به cons، به cons بعدی اشاره می‌کند به جز آخرین cons که مقدارش به nil اشاره می‌کند.consها به راحتی برای پیاده‌سازی درخت‌ها و دیگر ساختمان‌های دادهٔ پیچیده استفاده می‌شوند: اگر چه توصیه می‌شود که از نمونه‌های کلاس یا ساختار به جای آن استفاده شود.لیسپ معمولی آرایه‌های چند بعدی را پشتیبانی می‌کند، و می‌تواند به صورت پویا در صورت نیاز آرایه‌ها را دوباره سایز دهی بکند. آرایه‌های چند بعدی می‌تواند برای ریاضیات ماتریسی به کار روند. بردار یک آرایهٔ یک بعدی است. آرایه‌ها می‌توانند هر نوع داده‌ای را به عنوان اعضاء داشته باشند (حتی انواع ترکیبی در همان آرایه) یا می‌توانند برای شامل شدن نوع خاصی از اعضاء، تخصصی شوند مثلاً دربرداری از اعداد صحیح. بسیاری از پیاده‌سازی‌ها می‌توانند توابع آرایه‌ای را وقتی که آرایه‌ها در نوع‌های تخصصی شده به کار می‌روند، بهینه کند. دو نوع آرایه‌ای تخصصی شده، استاندارد هستند: رشته برداری از کاراکترهاست در حالی که بردار بیتی، برداری از بیت‌ها است.جداول Hash پیوستگی بین شی‌های داده‌ای را ذخیره می‌کند. هر شی ممکن است به عنوان کلید یا مقدار استفاده شود. جداول Hash نیز مانند آرایه‌ها می‌توانند به صورت اتوماتیک در مواقع نیاز دوباره سایزدهی شوند.بسته‌ها مجموعه‌ای از سمبل‌ها هستند که به‌طور عمده برای جداسازی بخش‌های یک برنامه به فضاهای نامی به کار می‌روند. یک بسته بعضی از سمبل‌ها را خارج کرده و به عنوان بخشی از یک واسط عمومی مشخص می‌کند.ساختارها، شبیه structها در Cو رکوردها در پاسکال، ساختمان‌های داده‌ای پیچیدهٔ دلخواه با هر عدد و نوعی از زمینه‌ها را نشان می‌دهند.توابع.در لیسپ معمولی، نوع داده یک نوع دادهای است. به عنوان نمونه، این امکان وجود دارد که تابعی نوشته شود که توابع دیگر را به عنوان آرگومان می‌پذیرد و همین‌طور به عنوان خروجی برمی‌گرداند. این خواصیت این امکان را فراهم می‌کند که عملیات بسیار عمومی را به توان تشریح کرد.کتابخانه لیسپ معمولی شدیداً به چنین توابع مرتبه بالاتری تکیه می‌کند. مثلاً تابع sort عملگر مقایسه را به عنوان آرگومان می‌پذیرد؛ بنابراین نه تنها می‌تواند هر نوع داده‌ای را مرتب کند بلکه ساختمان داده را نیز مطابق با یک کلید مرتب می‌کند.لیست را با استفاده از اپراتور &lt;به عنوان عملگر مقایسه‌کننده مرتب می‌کند؛ و عبارت روبرو رابرمی گرداند (۶ ۵ ۴ ۳ ۲ ۱): (sort (list 5 2 6 3 1 4) #'&gt;)لیست را مطابق با عنصر اول از هر زیر لیست مرتب می‌کند و (۳b) (4 c) (9 a) را برمی‌گرداند: (sort (list '(9 A) '(3 B) '(4 C)) #'&lt;:key #'first)مدل عرض یابی برای توابع بسیار ساده‌است. وقتی که عرضیاب‌کننده با فرم (F A۱ A۲. . .) مواجه می‌شود باید فرض کند که سمبولی که F نامیده می‌شود یکی از گزینه‌های زیر است:اگر F نام یک تابع باشد، آنگاه آرگومان‌های A1, A۲، … An با ترتیب چپ به راست عرض یابی می‌شوند و آن مقادیر را به عنوان پارامتر می‌گیرد.فضای نامی تابعدر اینجا یک تفاوت اساسی بین لیسپ معمولی و Scheme وجود دارد. در CL، نام تابع در یک فضای نامی جستجو می‌شود که از فضای نامی مربوط به متغیرها جدا می‌باشد و فضای نامی تابع نامیده می‌شود. عملگرهایی که نام‌ها را در فضای عمومی تعریف می‌کنند شامل defun, flet و labels هستند.برای فرستادن تابع با اسم به عنوان یک آرگومان به تابع دیگر، بعد از عملگر ویژه تابع که عموماً با علامت # ' خلاصه می‌شود استفاده کرد. مثال sort اول به تابعی اشاره می‌کند که نام &lt;در فضای نامی تابع، با کد #'&gt; دارد.مدل ارزیابی Scheme ساده‌تر است تنها یک فضای نامی وجود دارد و همه مکان‌ها در فرم ارزیابی می‌شوند (با هر ترتیب) — نه فقط آرگومان‌ها. چگاهی برای برنامه نویسان با تجربه، کدی که در یک نسخه نوشته شده در نسخه‌های دیگر گیج‌کننده‌است. به‌طور نمونه، بسیاری از برنامه نویسان CL ممکن است از نام‌های متغیر توصیفی مثل لیست یا رشته استفاده کنند که در Scheme غیرمجاز است و آن‌ها با نام‌های توابع برخورد پیدا می‌کنند. اگر چه فضای نامی مجزا برای توابع یک حسن است، یک منبع مجادله در خانوادهٔ لیسپ می‌باشد؛ که معمولاً به عنوان Lisp-۱ و Lisp-۲ مورد ارجاع قرار می‌گیرد. این اسامی در مقاله‌ای در سال ۱۹۸۸ از ریچارد پ. گابریل ایجاد شد که به‌طور جامع ای دو روش را مقایسه می‌کند.سرانجام، در حالی که تعریف یک تابع (شکل befun) یک لیست است، توابع عموماً به صورت داخلی به صورت لیست نشان داده نمی‌شوند.انواع دیگر.انواع دیگر داده‌ای در لیسپ معمولی شامل موارد زیر است:لیسپ معمولی در ضمن شامل جعبه ابزاری برای برنامه‌نویسی شی گرا به نام سیستم شی ای لیسپ معمولی یا CLOS است.ماکروها.یک ماکرو در Lisp به‌طور سطحی شبیه یک تابع در حال استفاده‌است. اگرچه، نشان دهندهٔ عبارتی است که ارزیابی شده‌است، نمایندهٔ یک تغییر شکل کد اصلی برنامه نیز می‌باشد. ماکروها به برنامه نویسان لیسپ امکان ایجاد فرم‌های نحوی جدید در زبان را می‌دهد. به عنوان نمونه، این ماکرو شکل حلقه until را ایجاد می‌کند، که ممکن است در زبان‌هایی مثل Perl آشنا به نظر می‌رسد: (defmacro until (test &amp;body body) `(do () (,test) ,@body)) ;; example (until (= (random 10) 0) (write-line "Hello"))همهٔ ماکروها باید قبل از این که کد اصلی شامل آن‌ها ارزیابی یا کامپایل شود، گسترش یابند. ماکروها می‌توانند به عنوان توابعی که درخت‌های نحوی انتزاعی را می‌پذیرند و برمی‌گردانند ملاحظه شوند. این توابع قبل از اینکه کامپایلر کد اصلی نهایی را تولید کند، احضار می‌شوند. ماکروها در لیسپ معمولی معمولی نوشته شده‌اند، و هر عملگر لیسپ معمولی را می‌توانند استفاده کنند. نکته‌ای که در بالا ذکر شد توسط لیسپ معمولی برای ساده کردن مورد معمول از جایگزینی در قالب‌های یک کد، ایجاد شده‌است.گرفتن متغیرها و سایه اندازی آن‌ها.ماکروهای لیسپ معمولی قادر به گرفتن متغیر هستند، موقعیتی که در آن‌ها سمبل‌ها در بدنه گسترش یافتهٔ ماکرو با سمبل‌های متن فراخوانی شده و منطبق می‌شوند. گرفتن متغیرها گاهی اوقات اثر مطلوبی دارد: به برنامه نویسان امکان ایجاد ماکروها را جایی که سمبل‌های مختلف، معنایی ویژه دارند، می‌دهد. اگرچه، می‌تواند خطاهای غیرمعمول و غیرقابل انتظاری را نیز ایجاد کند.بعضی از سیستم‌های لیسپ مانند scheme، با استفاده از ماکروها از گرفتن متغیر جلوگیری می‌کنند — که ماکروهای تمیز نامیده می‌شوند. در لیسپ معمولی می‌توان بوسیلهٔ gensyms از گرفتن متغیرهای ناخواسته جلوگیری کرد – gensyms سمبل‌های واحد گارانتی شده‌ای هستند که می‌توانند در گسترش ماکروها بدون خطر گرفته شدن استفاده شوند.مسئلهٔ دیگر سایه اندازی غیرعمدی عملگرهای استفاده شده در گسترش ماکروها است. مثلاً، کد زیر را ملاحظه کنید که یک گرفتن متغیر غیرعمدی را نشان می‌دهد: ;; expansion of UNTIL makes liberal use of DO (defmacro until (expression &amp;body body) `(do () (,expression) ,@body)) ;; macrolet establishes lexical operator binding for DO (macrolet ((do (...) ... something else ...)) (until (= (random 10) 0) (write-line "Hello")))ماکرو UNTIL به شکلی گسترش می‌یابد که DO را فراخوانی کند، که به منظور ارجاع شکل ویژه پایه‌ای DO طرح‌ریزی شده‌است. اگر چه، در این متن، DO ممکن است معنای کاملاً متفاوتی داشته باشد.لیسپ معمولی مشکل سایه اندازی عملگر را با ممانعت از تعریف مجدد عملگرهای ساختمانی مثل DO در این مثال، اصلاح می‌کند. در ضمن، کاربران ممکن است کدهایشان را به بسته‌هایی تقسیم کنند. سمبل‌های ساختمانی در بستهٔ لیسپ معمولی p یافت می‌شوند، که بوسیلهٔ سمبل‌ها در بستهٔ کاربر سایه اندازی نمی‌شوند.مقایسه با Lispهای دیگر.لیسپ معمولی بسیار با Scheme مقایسه می‌شود. چون آن‌ها دو نسخهٔ معروف از Lispها هستند. Scheme از لحاظ تاریخی جدیدتر از LC است، و نه تنها از همان Lisp می‌آید بلکه به وسیله بعضی از همان مهندسین نیز ارائه شده‌است.Guy L. Steele با Gerald Jay Sussman, Scheme را طراحی کردند و کمیته استاندارد را برای لیسپ معمولی به کرسی نشاندند.اغلب سیستم‌های Lisp که طراحی‌هایشان در لیسپ معمولی توزیع شده مثل Zetalisp و Franz Lisp تنها از متغیرهایی که به صورت پویا محدود شده‌اند استفاده کرده‌اند. Scheme متغیرهایی را به Lisp معرفی می‌کند که از لحاظ لغوی محدود شده‌اند و به صورت گسترده‌ای به عنوان یک ایدهٔ خوب شناخته شده و توسط CL اقتباس شده‌اند. CL متغیرهای محدود شدهٔ پویا را پشتیبانی می‌کند اما باید به‌طور صریح ذکر شود که آن‌ها دارای این مشخصه هستند.لیسپ معمولی گاهی Lisp۲ نامیده می‌شود و Scheme, Lisp۱ که برمی گردد به استفادهٔ CL از فضاهای نامی مجزا برای توابع و متغیرها، (در حقیقت، CL فضاهای نامی زیادی دارد مانند آن‌هایی که بری کلمات کلیدی loop و نام‌های بلوکی و قالب go به کار می‌روند).به علاوه پیاده‌سازی‌ها قصد دارند به مجموعه‌های منشعبی از بسته‌های کتابخانه برسند که عملکردی را که در استاندارد پوشش داده نشده، تأمین کنند. بعضی از این خصیصه‌ها به استاندارد اضافه شدند مانند CLOS و قرارداد LOOP؛ بقیه ویژهٔ پیاده‌سازی باقی ماندند.متأسفانه بسیاری از وسایل ارزشمند برای برنامه‌نویس مدرن مثل شبکه بندی TCP/IP همچنان استاندارد نشده باقی مانده‌اند. اگر چه، بسته‌های با کد باز برای پشتیبانی چنین خصیصه‌هایی به روش قابل انتقال ایجاد شده‌اند، یک نمونه قابل توجه آن پروژهٔ مجمومهٔ کد باز لیسپ معمولی است.لیسپ معمولی برای پیاده‌سازی وسیلهٔ کامپایلیرهای افزایشی طراحی شده‌است. تعریف‌های استاندارد به منظور بهینه کردن کامپایل در مشخصات زبان پیشنهاد شده‌است. اغلب پیاده‌سازی‌های لیسپ معمولی، توابع را برای بومی‌کردن کد ماشین کامپایل می‌کنند. بقیه به کد بایت کامپایل می‌کنند، که سرعت را کاهش می‌دهد ولی قابلیت انتقال کد باینری را آسان می‌کند. این تصور غلط که Lisp یک زبان کاملاً تفسیر شده‌است، بسیار متحمل است در نتیجهٔ این حقیقت باشد که محیط‌های لیسپ معمولی یک اعلان با اثر متقابل را تأمین می‌کند و اینکه توابع یکی یکی به یک ترتیب افزایشی کامپایل می‌شوند.بعضی از پیاده‌سازی‌ها براساس Unix مثل CLISP، می‌توانند به عنوان مفسرهای متنی استفاده شوند؛ یعنی به وسیله سیستم به صورت شفاف به ترتیبی که مفسر Perl ویا Unix shell است، احضار شوند.لیست پیاده‌سازی‌ها.پیاده‌سازی‌های قابل توزیع مجدد رایگان شامل موارد زیر است:برای ویندوز، FreeBsd، لینوکس، Apple Mac OS X، یونیکس و انواع مختلف آن. Allegro CL یک محیط توسعه یکپارچه (برای ویندوز و لینوکس) فراهم می‌کند و قابلیت‌های گسترده‌ای را برای تحویل درخواست‌های نرم‌افزارها دارد.پیاده‌سازی لیسپ معمولی برای ویندوز.برای ویندوز، FreeBsd، لینوکس، Apple Mac OS X یونیکس و انواع مختلف آن.LispWorks یک محیط توسعه مجتمع (در دسترس برای همه سیستم‌عامل) و قابلیت‌های گسترده‌ای را فراهم می‌آورد.که برای محاسبات با کارایی بالا - علمی طراحی شده‌است.نوعی پیاده‌سازی لیسپ معمولی است که بر روی ماشین مجازی جاوا اجرا می‌شود شامل یک کامپایلر افزون بر Java byte code، و به لیسپ اجازه دسترسی به کتابخانه‌های جاوا را می‌دهد. مسلح خرس کلر—هر چند از آن استفاده می‌شود Armed Bear Common Lisp در حال حاضر یک پروژه مستقل است.در اصل از دانشگاه کارنگی ملون که در حال حاضر به وسیلهٔ کاربران متعدد استفاده می‌شود. CMUCL از یک کامپایلر اصلی سریع مشهور استفاده می‌کند و شامل مفسر نمی‌باشد، به‌طور گسترده‌ای از پیاده‌سازی CL با کد منبع باز استفاده می‌کند، در لینوکس و بی‌اس‌دی برای اینتل x۸۶ موجود هستند.نوعی دیگر از لیسپ معمولی‌های متن باز می‌باشد.یک انشعاب از CMUCL است. SBCL با تأکید بیشتر روی قابلیت نگهداری، از CMUCL باز شناخته می‌شود. SBCL روی محیط CMUCL اجرا می‌شود بجز HP/UX؛ به علاوه روی لینوکس برای PowerPC, SPARC و MIPS و روی سیستم‌عامل Mac اجرا می‌شود.کامپایلر Lisp پروژهٔ GNU. GCL هنوز کاملاً آمادهٔ انجام ANSI نیست ولی پیاده‌سازیی از انتخاب برای پروژه‌های بزرگ مختلف شامل ابزارهای ریاضی Maxima و ACL۲ است.که برای جاسازی شدن در کاربردهای C طراحی شده‌است.یک شاخهٔ کد منبع باز از لیسپ معمولی مکینتاش. همانطوری‌که از اسم آن حاکی است، OpenMCL ویژهٔ مکینتاش است و روی سیستم‌عامل Mac, Darwin و یونیکس برای PowerPC اجرا می‌شود.محیط Lisp را برای کامپیوترهای x۸۶ بدون تکیه بر سیستم‌عامل تکمیل می‌کند.همچنین پیاده‌سازی‌های موجود غیر رایگانی از Franz, Xanalys, Digitool, Corman و Scieneer وجود دارد.کاربردها.با وجود انتظارات بزرگ از کمیتهٔ استاندارد (CL گاهی به عنوان جایگزینی برای C معرفی می‌شود)، لیسپ معمولی یک زبان برنامه‌نویسی مناسب باقی ماند، که اغلب در دانشگاه یا محیط‌های کاربردی ویژه که در ارتباط با هوش مصنوعی است به کار می‌رود.موارد کاربردیلیسپ معمولی در بسیاری از برنامه‌های تجاری استفاده می‌شود، از جمله یاهو! سایر نمونه‌های قابل توجه عبارتند از:همچنین برنامه‌های متن باز هم به با کمک لیسپ معمولی نوشته شده‌است که می‌توان به نمونه‌های زیر اشاره کرد:منابع.دانشنامه آزاد انگلیسی