لیسپ معمولی
لیسپ معمولی، که معمولاً به صورت CL مخفف میشود، یک نوع از لیسپ است که به وسیلهٔ ANSI *۳۰۲۶۶ - ۱۹۹۴ استاندارد شده و برای استاندارد کردن نسخههای منشعب شدهٔ لیسپ که بخشهایی از آن را دارا هستند، گسترش یافتهاست. CL در واقع یک پیاده سازی نیست بلکه یک مشخصهٔ زبانی است که پیاده سازیهای لیسپ با آن مطابقت دارد. لیسپ معمولی یک زبان برنامه نویسی همه منظورهاست، در مقایسه با نسخههای لیسپ مانند Lisp Emacs و Auto Lisp که زبانهای جامع جاسازی شده در تولیدات ویژه هستند. برخلاف بسیاری از لیسپهای اولیه، لیسپ معمولی مانند 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 عملگر مقایسه را به عنوان آرگومان میپذیرد. بنابراین نه تنها میتواند هر نوع دادهای را مرتب کند بلکه ساختمان داده را نیز مطابق با یک کلید مرتب میکند.
لیست را با استفاده از اپراتور < به عنوان عملگر مقایسه کننده مرتب میکند. و عبارت روبرو رابرمی گرداند ( ۶ ۵ ۴ ۳ ۲ ۱ ):
(sort (list 5 2 6 3 1 4) #'>)
لیست را مطابق با عنصر اول از هر زیر لیست مرتب میکند و ( ۳b ) ( ۴ c ) ( ۹ a ) را برمی گرداند:
(sort (list '(9 A) '(3 B) '(4 C)) #'< :key #'first)
مدل عرض یابی برای توابع بسیار سادهاست. وقتی که عرضیاب کننده با فرم (F A۱ A۲. . . ) مواجه میشود باید فرض کند که سمبولی که F نامیده میشود یکی از گزینههای زیر است:
- یک عملگر ویژه ( به آسانی در یک لیست ثابت چک میشود).
- یک عملگر ماکرو ( باید قبلاً تعریف شده باشد)
- نام یک تابع ( پیش فرض، که ممکن است یک سمبل یا یک زیر شکل باشد که با سمبل lambda شروع میشود.
اگر F نام یک تابع باشد، آنگاه آرگومانهای A۱، A۲، ... An با ترتیب چپ به راست عرض یابی میشوند و آن مقادیر را به عنوان پارامتر میگیرد. فضای نامی تابع
در اینجا یک تفاوت اساسی بین لیسپ معمولی و Scheme وجود دارد.در CL، نام تابع در یک فضای نامی جستجو میشود که از فضای نامی مربوط به متغیرها جدا میباشد و فضای نامی تابع نامیده میشود. عملگرهایی که نامها را در فضای عمومی تعریف میکنند شامل defun، flet و labels هستند. برای فرستادن تابع با اسم به عنوان یک آرگومان به تابع دیگر، بعد از عملگر ویژه تابع که عموماً با علامت # ' خلاصه میشود استفاده کرد. مثال sort اول به تابعی اشاره میکند که نام < در فضای نامی تابع، با کد #'> دارد. مدل ارزیابی Scheme ساده تر است تنها یک فضای نامی وجود دارد و همه مکانها در فرم ارزیابی میشوند (با هر ترتیب ) — نه فقط آرگومانها.چ گاهی برای برنامه نویسان با تجربه، کدی که در یک نسخه نوشته شده در نسخههای دیگر گیج کنندهاست. به طور نمونه، بسیاری از برنامه نویسان CL ممکن است از نامهای متغیر توصیفی مثل لیست یا رشته استفاده کنند که در Scheme غیر مجاز است و آنها با نامهای توابع برخورد پیدا میکنند. اگر چه فضای نامی مجزا برای توابع یک حسن است، یک منبع مجادله در خانوادهٔ لیسپ میباشد. که معمولاً به عنوان Lisp-۱ و Lisp-۲ مورد ارجاع قرار میگیرد. این اسامی در مقالهای در سال ۱۹۸۸ از ریچارد پ. گابریل ایجاد شد که به طور جامع ای دو روش را مقایسه میکند. سرانجام، در حالی که تعریف یک تابع ( شکل befun ) یک لیست است، توابع عموماً به صورت داخلی به صورت لیست نشان داده نمیشوند.
انواع دیگر[ویرایش]
انواع دیگر دادهای در لیسپ معمولی شامل موارد زیر است:
- نام مسیر که نماینده فایلها و شاخهها در سیستم فایلی است. چون از لحاظ قدمت Lisp جدای از Unix بود، ویژگی نام مسیر لیسپ معمولی عمومی تر از قراردادهای نام فایل بیشتر سیستمعاملها است و این ویژگی دسترسی به فیلها را در برنامههای Lisp به طور گستردهای قابل انتقال در سیستمهای گوناگون میکند.
- جریانهای ورودی و خروجی نشان دهنده تخلیه و تغذیهٔ دادههای متنی یا باینری هستند مانند فایلهای باز یا نمایی.
- لیسپ معمولی دارای بلوک ساختمانی تولید کننده اعداد تصادفی کاذب هستند. اشیاء تصادفی نماینده منابع قابل استفادهٔ مجدد اعداد تصادفی کاذب هستند و به کاربر اجازه میدهند که PRNG را راه اندازی کند یا منجر به اجرای مجدد یک توالی از آن شود.
- شرایط یک نوع ویژهاست که برای نشان دادن خطاها، استثناها و دیگر وقایع که یک برنامه ممکن است به آنها پاسخ دهد استفاده میشوند.
لیسپ معمولی در ضمن شامل جعبه ابزاری برای برنامه نویسی شی گرا به نام سیستم شی ای لیسپ معمولی یا CLOS است.
ماکروها[ویرایش]
یک ماکرو در Lisp به طور سطحی شبیه یک تابع در حال استفاددهاست. اگرچه، نشان دهندهٔ عبارتی است که ارزیابی شدهاست، نمایندهٔ یک تغییر شکل کد اصلی برنامه نیز میباشد. ماکروها به برنامه نویسان Lisp امکان ایجاد فرمهای نحوی جدید در زبان را میدهد. به عنوان نمونه، این ماکرو شکل حلقه until را ایجاد میکند، که ممکن است در زبانهایی مثل Perl آشنا به نظر میرسد:
(defmacro until (test &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 &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 است، احضار شوند.
لیست پیاده سازیها[ویرایش]
پیاده سازیهای قابل توزیع مجدد رایگان شامل موارد زیر است:
- Allegro Common Lisp
برای ویندوز ، FreeBsd، لینوکس ، Apple Mac OS X، یونیکس و انواع مختلف آن. Allegro CL یک محیط توسعه یکپارچه (برای ویندوز و لینوکس) فراهم میکند و قابلیتهای گستردهای را برای تحویل درخواستهای نرمافزارها دارد.
- Corman Common Lisp
پیاده سازی لیسپ معمولی برای ویندوز.
- LispWorks
برای ویندوز ، FreeBsd، لینوکس ، Apple Mac OS X یونیکس و انواع مختلف آن.LispWorks یک محیط توسعه مجتمع (در دسترس برای همه سیستمعامل) و قابلیتهای گستردهای را فراهم میآورد.
- Scieneer Common Lisp
که برای محاسبات با کارایی بالا - علمی طراحی شدهاست.
- Armed Bear Common Lisp
نوعی پیاده سازی لیسپ معمولی است که بر روی ماشین مجازی جاوا اجرا میشود شامل یک کامپایلر افزون بر Java byte code، و به لیسپ اجازه دسترسی به کتابخانههای جاوا را میدهد. مسلح خرس کلر -- هر چند از آن استفاده میشود Armed Bear Common Lisp در حال حاضر یک پروژه مستقل است
- CMUCL
در اصل از دانشگاه کارنگی ملون که در حال حاضر به وسیلهٔ کاربران متعدد استفاده میشود. CMUCL از یک کامپایلر اصلی سریع مشهور استفاده میکند و شامل مفسر نمیباشد، به طور گستردهای از پیاده سازی CL با کد منبع باز استفاده میکند، در Linux و BSD برای اینتل x۸۶ موجود هستند.
- GNU CLISP
نوعی دیگر از لیسپ معمولیهای متن باز میباشد
- Steel Bank Common Lisp) SBCL)
یک شاخه از CMUCL است. SBCL با تاکید بیشتر روی قابلیت نگهداری، از CMUCL باز شناخته میشود. SBCL روی محیط CMUCL اجرا میشود بجز HP/UX؛ به علاوه روی لینوکس برای PowerPC، SPARC و MIPS و روی سیستمعامل Mac اجرا میشود.
- GNU Common Lisp) GCL)
کامپایلر Lisp پروژهٔ GNU. GCL هنوز کاملاً آمادهٔ انجام ANSI نیست ولی پیاده سازیی از انتخاب برای پروژههای بزرگ مختلف شامل ابزارهای ریاضی Maxima و ACL۲ است.
- لیسپ معمولی قابل جاسازی
که برای جاسازی شدن در کاربردهای C طراحی شدهاست.
- OpenMCL
یک شاخهٔ کد منبع باز از لیسپ معمولی مکینتاش. همانطوری که از اسم آن حاکی است، OpenMCL ویژهٔ مکینتاش است و روی سیستمعامل Mac، Darwin و یونیکس برای PowerPC اجرا میشود.
- Movitz
محیط Lisp را برای کامپیوترهای x۸۶ بدون تکیه بر سیستمعامل تکمیل میکند.
همچنین پیاده سازیهای موجود غیر رایگانی از Franz، Xanalys، Digitool، Corman و Scieneer وجود دارد.
کاربردها[ویرایش]
با وجود انتظارات بزرگ از کمیتهٔ استاندارد (CL گاهی به عنوان جایگزینی برای C معرفی میشود)، لیسپ معمولی یک زبان برنامه نویسی مناسب باقی ماند، که اغلب در دانشگاه و یا محیطهای کاربردی ویژه که در ارتباط با هوش مصنوعی است به کار میرود. موارد کاربردی
لیسپ معمولی در بسیاری از برنامههای تجاری استفاده میشود، از جمله یاهو! سایر نمونههای قابل توجه عبارتند از :
- بازی jak and daxter در کنسول پلس استیشن
- OpenMusic یک شیء گرا محیطهای برنامه نویسی و تصویری مبتنی بر لیسپ معمولی،
- موتور جستجوی نرمافزار ITA که توسط سایتهای گردشگری مانند orbitz و kayak.com و خطوط هواپیمایی مانندContinental Airlines، American Airlines و US Airlines استفاده میشود
همچنین برنامههای متن باز هم به با کمک لیسپ معمولی نوشته شدهاست که میتوان به نمونههای زیر اشاره کرد:
- Maxima، یک سیستم پیچیده جبر کامپیوتری
- Stumpwm یک window manager بر اساس صفحه کلید تماماً به وسیله لیسپ معمولی نوشته شدهاست
- acl۲، کاربردی، یک ثابت کننده نظریه با تمام خصیصهها برای زیر مجموعهای از لیسپ معمولی است
- Compo، زبانی که به ساختارهای موسیقی پیچیده اجازه توصیف به یک روش طبیعی را میدهد.
- Lisa، سیستم تولید قانون برای ساختن نمایندههای نرمافزاری "هوش"
منابع[ویرایش]
دانشنامه آزاد انگلیسی [۱]
صفحه اصلی زبان CLISP [۲]
مقالهای راجع به لیسپ معمولی:[۳]
|
|||||||||||
|
|||||||||||||||||||||||||||||||||||||||||