موضوع مقاله: لیسپ | مخاطب: عمومی | لحن: دانشنامه‌ای | ساختار: عنوان، مقدمه، 3 بخش، جمع‌بندی | مقاله: | # لیسپ | مقدمه: لیسپ یک زبان برنامه‌نویسی رایانه است که در سال ۱۹۵۸ به وسیلهٔ جان مک‌کارتی ابداع شده‌است. | ## بخش 1: لیسپ | این زبان، مانند زبان برنامه‌نویسی پرولوگ، بیشتر برای برنامه‌نویسی هوش مصنوعی مورد استفاده قرار می‌گیرد و با توجه به اینکه زبان لیسپ از نحو ساده‌ای برخوردار است، تجزیه و پیاده‌سازی آن نسبتاً با سهولت انجام می‌شود. یکی از ویژگی‌های جالب زبان لیسپ این است که خود برنامه‌های لیسپ نیز فهرست هستند و بنابراین، می‌توان با برنامه‌ها به عنوان داده‌ها رفتار کرد یا داده‌ها را به عنوان برنامه ارزیابی نمود. لیسپ دارای گویش‌های مختلفی است که بعضی از آن‌ها دارای قابلیت‌های شیءگرا نیز هستند. در ابتدا لیسپ به عنوان علامت‌گذاری و نمادسازی ریاضیات و برای برنامه‌نویسی رایانه ابداع شد. زبان لیسپ به سرعت مورد توجه برنامه نویسان از جمله برای تحقیقات علمی هوش مصنوعی قرار گرفت. لیسپ یکی از ابتدایی‌ترین زبان‌های برنامه‌نویسی می‌باشد و در علوم رایانه بر بسیاری از تفکرات و ایده‌ها پیشگام بود. لیسپ شامل ساختمان دادهٔ درخت، مدیریت نگهداری اتوماتیک، برنامه‌نویسی پویا، برنامه‌نویسی شیء گرا و کامپایلر مستقل می‌باشد. لینک لیست یکی از قسمت‌های اصلی ساختمان دادهٔ زبان لیسپ است و سورس کد لیسپ از لیست‌ها ساخته شده‌است و می‌تواند به عنوان ساختمان داده عمل کند. پیشرفت و توسعهٔ سیستم ماکرو به برنامه‌نویسان اجازه می‌دهد تا ترکیب‌های جدید ویا حتی حیطهٔ زبان‌های برنامه‌نویسی ویژه‌ای را ایجاد کرده و در زبان لیسپ تعبیه کنند. قابلیت تبادل کدها و داده‌ها به زبان لیسپ قابلیت تشخیص ترکیب‌ها را می‌دهد، همهٔ کدهای برنامه به صورت عبارت‌های نمادین یا لیست‌های پرانتزگذاری شده نوشته شده‌اند. یک تابع می‌تواند توسط خودش و یا توابع دیگر فراخوانی شود و یا طبق قواعد نحوی نوشتن یک لیست و استفاده از اول نام عملگرها و پیروی کردن از قواعد آرگومان‌ها ایجاد شود. به عنوان مثال تابع f دارای ۳ آرگومان می‌باشد و به صورت مقابل توانایی فراخوانی را دارد و مورد استفاده قرار می‌گیرد: (f x y z) تاریخچه زبان لیسپ زبان برنامه‌نویسی لیسپ توسط جان مک کارتی در سال ۱۹۵۸ در حالی که در مؤسسهٔ فناوری ماساچوست (MIT) بود ابداع شد. مک کارتی طرح خودش را در یک مقالهٔ مرتبط با انجمن ماشین آلات کامپیوتری در سال ۱۹۶۰ منتشر کرد. طرح وی در ابتدا به صورت «بخش اول: توابع بازگشتی از دید عبارت‌های نمادین و محاسبهٔ آن‌ها توسط ماشین» ارائه شد و بخش دوم آن هیچگاه منتشر نشد. وی نشان داد که با یک تعداد ساده و کمی از عملگرها و علامت‌گذاری توابع می‌توان یک زبان تورینگ کامل برای الگوریتم‌ها ایجاد کرد. از سال ۱۹۵۵ یا ۱۹۵۶ و پیش از آن ایده‌های بسیاری بر زبان لیسپ وارد شد از جمله پردازش لیست و توابع بازگشتی که در زبان لیسپ به کار برده شد. ثبت‌های اصلی مک کارتی به صورت عبارت‌های غیر نمادین که خواستار تفسیر کردن و برگرداندن به عبارت‌های نمادین بود. برنامه نویسان به سرعت عبارت نمادین را انتخاب و عبارت‌های غیر نمادین را ترک کردند. راسل مقالهٔ مک کارتی را مطالعه کرد و دریافت که توابع لیسپ می‌توانند در کد ماشین اجرا شوند. این نتیجه از مطالعه و دریافت راسل نشان می‌دهد که مفسر لیسپ می‌توانست برای اجرای برنامه‌های لیسپ و ارزیابی صحیح عبارت لیسپ استفاده شود. دو زبان اسمبلی به عنوان دو عملیات اصلی و ابتدائی تجزیه و جدا کردن عناصر اصلی لیست برای IBM 704 شد. این دو زبان اسمبلی car (مضمون آدرس ثبات) و cdr (محتوای کاهش میزان ثبات‌ها) نسخهٔ لیسپ هنوز ازcar وcdr برای عملیاتی که اولین عنصر در یک لیست و باقی‌ماندهٔ لیست را برمی‌گرداند، استفاده می‌کند. اولین کامپایلر تکمیل شدهٔ لیسپ، در سال ۱۹۶۲توسط تام هارت و مایک لوین در MIT اجرا شد، این کامپایلر معرفی شده مدل لیسپ با کامپایلر نحوی در هر کامپایل و ترجمهٔ توابع می‌تواند به‌طور رایگان در هم بیامیزد. زبان به کار گرفته شده در ثبت هارت و لوین نسبت به کدهای ابتدائی مک کارتی به شیوهٔ لیسپ مدرن و جدید نزدیک تر می‌باشد. ویژگی‌های زبان لیسپ پیوستن به هوش مصنوعی بعد از شروع لیسپ، لیسپ به انجمن تحقیقاتی هوش مصنوعی پیوست، خصوصاً به سیستم‌های PDP، زبان لیسپ به عنوان پیاده‌ساز طرح کوچک زبان برنامه‌نویسی استفاده می‌شود که مبنایی برای سیستم معروف هوش مصنوعی SHRLU بود. | ## بخش 2: لیسپ | در سال ۱۹۷۰ تحقیقات علمی هوش مصنوعی به شاخه‌های تجاری انشعاب پیدا کرد که کارایی سیستم لیسپ موجود در این زمینه یک روند رو به رشد شد. لیسپ یک سیستم مشکل برای اجرا، مهارت کامپایلر و سخت‌افزار ذخیره‌کننده را در سال ۱۹۷۰ دارا باشد. بازیابی عادی حافظه، توسط دانشجوی فارغ‌التحصیل MIT (دانیل ادوارد) گسترش داده شده، که برای اجرای لیسپ روی سیستم‌های محاسباتی ساخته شده بود اما راندمان آن هنوز یک مشکل بود. برای رهبری ماشین لیسپ: سخت‌افزار اختصاصی برای اجرای محیط لیسپ و برنامه‌های آن استفاده می‌شود. پیشروی در هردو سخت‌افزار کامپیوتر و فناوری کامپایلر از ماشین‌های لیسپ از کار افتاده الهام گرفته شده‌است. طی شک کوشش بزرگ نسخه‌های بیشماری از زبان لیسپ را در یک زبان واحد متمرکز و متحد کردند (نسخه‌های برجسته و قابل ملاحظه‌ای شامل: اینترلیسپ، مک لیسپ، متالیسپ، و فرانزلیسپ) زبان‌های جدید (لیسپ عمومی و مشترک) در اصل یک زیر مجموعهٔ سازگاری از نسخه‌های تعویض شده بود. لیسپ عمومی و مشترک زبان برنامه‌نویسی فناوری اطلاعات ANSI X3.226-1994 در آن زمان فروشگاه‌های جهانی برای لیسپ خیلی کوچکتر از المان بود. ترکیب و معناشناسی لیسپ یک عبارت جهت‌دار است، برخلاف بیشتر زبان‌های دیگر، بین عبارت‌ها و جمله‌ها تمایز و فرقی وجود ندارد. همهٔ کدها و داده‌ها به عنوان عبارت‌ها نوشته شده‌اند – زمانی که یک عبارت ارزیابی می‌شود یک مقدار (یا یک لیستی از مقادیر) را می‌سازد، که آن هم در داخل عبارات دیگر جاسازی می‌شود. مقالهٔ ۱۹۵۸ مک کارتی دو نوع از ترکیب‌ها را معرفی کرد: عبارت نمادین Sexps هم نامیده می‌شود، که بازتابی از نمایش داخلی کدها و داده هاست و عبارت غیر نمادین هرگز مورد توجه قرار نگرفت و تقریباً همهٔ زبان‌ها امروزه از عبارات نمادین استفاده می‌کنند. استفاده از پرانتزگذاری‌ها تفاوت بسیار آشکار و مشهودی میان لیسپ و دیگر زبان‌های برنامه‌نویسی ایجاد کرده‌است. هرچند ترکیب عبارت‌های نمادین مسئولی برای توان لیسپ است، این ترکیب به شدت با قاعده و منظم است. هرچند ترکیبات لیسپ به نمادگذاری قدیمی محدود نشده‌اند می‌تواند به سبک‌های دیگر توسعه پیدا کند. تکیه روی عبارت‌ها، قابلیت انعطاف‌پذیری زیادی به زبان می‌دهد، زیرا توابع لیسپ به صورت لیست نوشته شده‌اند، آن‌ها دقیقاً مانند داده‌ها می‌توانند پردازش شوند، این قابلیت اجازه می‌دهد برنامه‌های لیسپ به سادگی و راحتی نوشته شوند و به نسبت برنامه‌های دیگر به راحتی اداره شوند. (برنامه‌نویسی غیر نمادین) بسیاری از نسخه‌های زبان لیسپ با عناصر جدا شده توسط فاصله‌های سفید و پرانتزگذاری شده‌ها نوشته می‌شود. برای مثال (1 2 f00) یک لیست است که عنصرهای آن سه اتم هستند (اتم: کوچکترین عضو لیست): این مقادیر ۱ و ۲ و F00 هستند. این مقادیر ضمناً دارای نوع داده‌ای خاصی هستند، مثلاً این لیست دارای دو عدد صحیح ۱ و ۲ و یک نوع دادهٔ ویژهٔ لیسپ که یک Symbol یا نماد نامیده می‌شود. عبات‌ها به عنوان لیست نوشته شده‌اند، استفاده کردن از ثبت‌های پیشوندی، عناصر ابتدایی در لیست نامی از یک شکل تابع، عملگرها، ماکروها یا اپراتورهای ویژه‌است. آرگومان‌ها باقی‌مانده‌هایی از لیست‌ها هستند، برای مثال تابع list آرگومان‌ها را به عنوان یک لیست برمی‌گرداند، بنابراین عبارت (list ‘۱ ‘۲ ‘foo) ارزیابی می‌شود و حاصل این ارزیابی لیست (۱٬۲،foo) می‌باشد. آرگومان‌های مثال قبل از اعداد هستند یعنی آرگومان‌های ویژه که این آرگومان‌ها از ارزیابی کردن آرگومان‌ها جلوگیری می‌کنند چون مقادیر آن‌ها مشخص است. هر عبارتی که بیان می‌شود قبل از اینکه با عبارات دیگر پیوست داده شود به صورت بازگشتی ارزیابی می‌شود. (list(1 2 (list(3 4 در این مثال حاصل ارزیابی به صورت لیست (۱٬۲(۳٬۴ می‌باشد، توجه کنید این لیست دارای ۳ آرگومان می‌باشد، لیست‌ها می‌توانند به صورت تو در تو باشند. عبارت معادل عبارت بالا به صورت ۱+۲+۳+۴ می‌باشد که از نشانگذاری میان وندی استفاده شده‌است. برای مثال، اپراتور ویژه if سه آرگومان می‌پذیرد، اگر اولین آرگومان صفر یا خالی باشد دومین آرگومان ارزیابی می‌شود و در غیر این صورت هٔرگومان سوم بررسی می‌شود. عبارت‌های لامبدا (Lambda) دیگر عبارت‌های ویژه لاندا می‌باشد که برای وصل کردن متغیرها به مقادیرشان که درون یک عبارت ارزیابی می‌شوند استفاده می‌شود. | ## بخش 3: لیسپ | آرگومان‌های درون لاندا یک لیستی از آرگومان‌ها هستند و عبارت ارزیابی توابع می‌باشند. عبارت (Lambda(arg +arg1 زمانی که این تابع به کار برده می‌شود به صورت یک تابع ارزیابی می‌شود و وظیفهٔ این تابع معرفی کردن یک آرگومان و اتصال دادن آرگومان به arg و در نهایت برگرداندن یک عدد بزرگتر از آرگومان قبلی می‌باشد عبارت‌های لاندا خیلی متفاوت با نام تابع رفتار نمی‌کند بنابراین اگر در عبارت (Lambda(arg +arg1 5->۶ عدد ۵ را وارد کنیم خروجی آن ۶ می‌شود. اتم‌ها: در نسخهٔ اصلی لیسپ دو نوع دادهٔ ابتدایی وجود دارد: اتم‌ها و لیست‌ها یک لیست یک رشتهٔ منظم و محدودی از عناصر می‌باشد، که هر عنصر در درون خودش یکی از این اتم‌ها یا لیست‌ها را دارد و یک اتم یک عدد یا یک نماد می‌باشد. تفاوت اصلی بین اتم‌ها و لیست‌ها این است که اتم‌ها تغییرناپذیر و منحصربه‌فرد می‌باشند. دو اتم که دقیقاً به یک صورت و به یک روش در یک شیء نوشته شده باشد در مکان متفاوتی در سورس کد ظاهر می‌شوند، هر لیست یک شیء مجزا می‌باشد و به خاطر اینکه مستقل از دیگر لیست هاست و از دیگر لیست‌ها به وسیلهٔ مقایسهٔ عملگرها مشخص می‌شود. دستورالعمل‌های پردازش لیست لیسپ دستورالعمل‌های زیادی را برای دستیابی و کنترل لیست‌ها فراهم می‌کند. توجه کنید که پردازهٔ Cons در هدایت و به کار بردن آرگومان‌های لیست نامتقارن است، بدین دلیل روش‌های لیست‌ها ایجاد می‌شوند. ساختار اشتراکی سریع تر از کپی کردن می‌تواند به صورت چشمگیری کارایی را بهبود بخشند. هرچند، این مهارت می‌تواند متقابلاً در راه‌های نامطلوب با عملکردهایی که تغییرات لیست‌های گذشته روی آرگومان‌های آن تأثیر بگذارد، اثر کند. زبان‌های برنامه‌نویسی Lisp معمولاً از یک خط دستور محاوره‌ای استفاده می‌کنند، که می‌تواند با یک محیط پیچیدهٔ گسترش یافته ترکیب شود. کاربر اصطلاحات و دستورها را در خط دستور وارد کرده یا با رهبری IDE آن‌ها را به سیستم Lisp می‌فرستد. این یک شرح ساده‌است که بسیاری از المان‌های Lispواقعی در آن نمی‌آید مانند ماکروها و کوئت‌ها. تابع read جملات متنی را به عنوان ورودی می‌پذیرد و آن‌ها را به ساختار لیست تجزیه می‌کند. به عنوان مثال، وقتی شما رشتهٔ (+ ۱ ۲) را در اعلان تایپ می‌کنید، تابع read آن را به یک لیست پیوندی حاصل از ۳ المان ترجمه می‌کند: علامت +، عدد ۱ و عدد ۲. تابع eval ساختار لیست را ارزیابی می‌کند و نوعی دیگر از ساختار را به عنوان نتیجه بازمی‌گرداند. ارزیابی کردن لزوماً تفسیر کردن معنی نمی‌دهد؛ بعضی سیستم‌های Lisp هر عبارتی را به زبان ماشین تبدیل می‌کنند. خیلی ساده‌است؛ به هر حال؛ برای تعریف ارزیابی به عنوان تفسیر: برای ارزیابی یک لیست که نام تابع دارد، eval ابتدا تمام آرگومان‌های داده شده به cdr اش را ارزیابی می‌کند و سپس تابع را روی آن آرگومان‌ها اعمال می‌کند. در این مثال، تابع عمل جمع است و به آرگومان‌های (۱ ۲) اعمال می‌شود که نتیجه ۳ است. یک عبارت که با قسمتی از ساختار لیست ارزیابی می‌شود میاز دارد که print لیست را به حرکت درآورد و در خروجی به شکل یک عبارت S نمایش دهد. برای اجرا کردن یک REPL در Lisp، تنها لازم است که این سه تابع را اجرا کنید و یک تابع حلقه بی‌نهایت را. موسسات متعارف علوم کامپیوتر Scheme بعضی دانشجویان را متقاعد می‌کند که تنها راه تکرار در زبان Lisp استفاده از بازگشت دم است؛ این اشتباه‌است. در نتیجه این حقیقت که بازگشت دم به عنوان یک جایگزین تصادفی برای استفاده از ساختارهای مبتنی بر تکرار (مانند do dolist loop) توصیه نمی‌شود تنها یک مسئلهٔ برتری ادبی نیست، ولی بالقوه یکی از کارآمدهاست (بعد از این که این روش فقط به عنوان یک پرش ساده به کار نرفت) و به عنوان یک تصحیح برنامه‌است. بعضی از ساختارهای کنترلی Lisp عملگرهای ویژه‌ای هستند، هم ارز کلیدواژه‌های ترکیبی باقی زبان‌ها. عباراتی که این عملگرها استفاده می‌کنند ظاهری شبیه فراخوانی تابع دارد، تفاوت اینجاست که آرگومان‌ها ضرورتاً نباید ارزیابی شوند یا در مورد تکرار شاید بارها ارزیابی شوند. در مقابل اکثر زبان‌های برنامه‌نویسی، Lisp به برنامه نویسان اجازه می‌دهد با خود زبان ساختارهای کنترلی را پیاده‌سازی کنند. | ## جمع‌بندی | ساختارهای کنترلی زیادی در ماکروهای Lisp پیاده‌سازی می‌شوند و برنامه نویسان می‌توانند هر ماکرو را گسترش دهند، برای آنانی که می‌خواهند بدانند چطور کار می‌کند.