Transcript Document

‫• معرفی زبان برنامه نویسی لیسپ‬
‫ارایه دهندگان‪:‬‬
‫آزاده دهقان رحمت آبادی‬
‫درسا رحمتیان‬
‫اسما ایزدی‬
‫نام استاد‪:‬‬
‫جناب آقای قاضی زاده‬
‫درس‪:‬‬
‫طراحی وپیاده سازی‬
‫‪2‬‬
‫‪lisp‬‬
‫دوشنبه‪2015/07/20 ،‬‬
INTRODUCTION TO LISP
‫‪4‬‬
‫‪lisp‬‬
‫دوشنبه‪2015/07/20 ،‬‬
‫فهرست‬
‫‪ .1‬معرفی زبان لیسپ‬
‫‪ .2‬نوع داده های لیسپ‬
‫‪ .3‬مقایسه زبان لیسپ و ‪c++‬‬
‫‪ .4‬ویژگی های زبان لیسپ‬
‫‪ .5‬برنامه نویسی ابتدایی به زبان لیسپ و اشنایی با‬
‫دستورات آن‬
‫‪5‬‬
‫‪lisp‬‬
‫دوشنبه‪2015/07/20 ،‬‬
‫قسمت اول ‪ :‬معرفی زبان برنامه نویسی لیسپ (‪)Lisp‬‬
‫‪( Lisp‬لیسپ) یک دسته از زبان های برنامه نویسی است که شامل چند‬
‫زبان برنامه نویسی است با تاریخچه ای طوالنی ‪ ،‬که همه چیز در آن به‬
‫صورت پرانتز گذاری شده و با نمایش ‪ prefix notation‬است که در‬
‫سال ‪ ۱۹۵۸‬ساخته شد‪.‬‬
‫‪ Lisp‬از نظر قدمت دومین زبان برنامه نویسی سطح باال ( ‪high-level‬‬
‫‪ ) programming language‬است که امروزه هم مورد استفاده قرار می‬
‫گیرد‪ .‬فقط زبان فورتن در زبان های سطح باالیی که هنوز استفاده می‬
‫شوند از لیسپ قدیمی تر است‪.‬‬
‫معروف ترین زبان های برنامه نویسی خانواده ی لیسپ زبان برنامه‬
‫نویسی ‪ Common Lisp‬و ‪ Scheme‬است‪.‬‬
‫‪6‬‬
‫‪lisp‬‬
‫دوشنبه‪2015/07/20 ،‬‬
‫لیسپ برای اهداف ریاضی درست شده بود که از روش عالمت‬
‫گذاری حسابگر‪ lambda‬آقای ‪ Alonzo Church‬استفاده می کرد‪.‬‬
‫لیسپ به سرعت به زبانی برای کارهای تحقیقاتی هوش مصنوعی تبدیل شد و‬
‫مورد توجه محققان در این زمینه قرار گرفت‪.‬‬
‫لیسپ که یکی از اولین زبان های ساخته شده بود در بسیاری از زمینه های علم‬
‫کامپیوتر پیشگام بود که در زیر بعضی از آن ها را مشاهده می کنید‪:‬‬
‫‪7‬‬
‫‪lisp‬‬
‫دوشنبه‪2015/07/20 ،‬‬
)tree data structures ( ‫ساختمان دادهای درخت‬

automatic ( ‫مدیریت ذخیره سازی اتوماتیک‬

)storage management
2015/07/20 ،‫دوشنبه‬
)dynamic typing( ‫نوع داده ای پویا‬

)conditionals( ‫دستورهای شرطی‬

)higher-order functions ( ‫تابع های سطح باال‬

)recursion( ‫تابع های بازگشتی‬

)‫ (معادل فارسی پیدا نکردم‬compile self-hosting

lisp
8
‫اسم “‪ ”Lisp‬از عبارت “ ‪ ” List Processing‬به دست آمده‬
‫است‪ .‬لیست پیوندی (‪ )Linked List‬یکی از مهم ترین ساختمان‬
‫داده ها در زبان لیسپ است و خود سورس کد زبان لیسپ هم لیست‬
‫است‪.‬‬
‫زبان برنامه نویسی لیسپ ‪ ,‬کد یک برنامه ی نوشته شده را می تواند‬
‫به عنوان یک ساختمان داده ی لیست بگیرد و آن را پردازش کند و‬
‫تغییراتی روی آن انجام دهد‪.‬‬
‫‪9‬‬
‫‪lisp‬‬
‫دوشنبه‪2015/07/20 ،‬‬
‫‪10‬‬
‫‪lisp‬‬
‫دوشنبه‪2015/07/20 ،‬‬
‫در شکل زیر نمودار زمانی شکل گیری زبان های عضو خانواده ی لیسپ‬
‫را می بینید‪.‬‬
‫‪11‬‬
‫‪lisp‬‬
‫دوشنبه‪2015/07/20 ،‬‬
‫قسمت دوم ‪ :‬نوع داده های زبان برنامه نویسی لیسپ‬
‫(‪)Lisp‬‬
‫همین طور که در مقدمه بررسی کردیم زبان لیسپ بیشتر برای کار های‬
‫محاسباتی و هوش مصنوعی طراحی شده است ‪ ،‬در زبان های برنامه‬
‫نویسی هوش مصنوعی ما بیشتر ازنوع داده های عددی به سیمبول ها‬
‫احتیاج داریم تا عبارات منطقی و گزاره ها را بررسی کنیم‪.‬به طور کلی نوع‬
‫داده در زبان برنامه نویسی لیسپ به صورت زیر است‪:‬‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫نوع داده های عددی‬
‫نوع داده ای کاراکتر‬
‫نوع داده های منطقی‬
‫نوع داده ای سمبول‬
‫‪12‬‬
‫‪lisp‬‬
‫دوشنبه‪2015/07/20 ،‬‬
‫نوع داده ای عددی در لیسپ‪:‬‬
‫نوع داده ای عددی در لیسپ شامل اعداد صحیح ‪ ،‬ممیز شناور ‪ ،‬مختلط‬
‫و کسری است‪.‬لیسپ معمولی از ‪ bignums‬برای نشان دادن مقدارهای‬
‫عددی با دقت و اندازه دلخواه استفاده میکند‪ .‬نوع کسری‪ ،‬کسرها را با‬
‫دقت نشان میدهد‪ ،‬این ویژگی در بسیاری از زبانها وجود ندارد‪ .‬لیسپ‬
‫معمولی به صورت اتوماتیک مقدارهای عددی را بین این دادهها به‬
‫صورت مناسب وارد میکند‪ .‬در لیسپ می توان با اعداد خیلی بزرگ‬
‫کار کرد بدون اینکه نگران سر ریز آن ها بود زیرا لیسپ یک رنج‬
‫‪13‬بزرگ را در اختیار می گذارد‬
‫‪lisp‬‬
‫دوشنبه‪2015/07/20 ،‬‬
‫‪ .‬در اسکرین شاتی که گرفتیم انواع نوع داده ای‬
‫عددی را در لیسپ می بینید‪:‬‬
‫همین طور که در شکل باال می بینید جذر عدد منفی چهار را به صورت عدد‬
‫مختلط چاپ کرده است‬
‫‪14‬‬
‫‪lisp‬‬
‫دوشنبه‪2015/07/20 ،‬‬
‫نوع داده ای کاراکتر ‪:‬‬
‫در لیسپ نوع داده ی دیگری به نام کاراکتر داریم که فقط محدود به‬
‫اعداد اسکی نیست و یونی کد ها را هم در بر می گیرد‪ .‬برای تعریف‬
‫داده های کاراکتری باید از \‪ #‬استفاده کرد مانند تصویر زیر که چند‬
‫نوع داده ی کاراکتری را مشخص کرده ام‪:‬‬
‫‪15‬‬
‫‪lisp‬‬
‫دوشنبه‪2015/07/20 ،‬‬
‫نوع داده ای منطقی‪:‬‬
‫در لیسپ نوع منطقی هم داریم که دو حالت درست و غلط را دارد‪.‬حالت درست‬
‫رابا ‪ true‬وحالت غلط را با ‪ NIL‬یا () نشان می دهیم ‪ .‬در شکل زیر ما تابع‬
‫‪ Listp‬را فرا خوانده ایم که خروجی اش یک مقدار منطقی است و می گوید‬
‫چیزی که تابع رویش فراخوانی شده است لیست است یا نه؟ ‪:‬‬
‫‪16‬‬
‫‪lisp‬‬
‫دوشنبه‪2015/07/20 ،‬‬
‫نوع داده ای سمبول‪:‬‬
‫مهم ترین نوع داده ای در لیسپ نوع سمبول است که در هوش مصنوعی ‪ ,‬پردازش‬
‫زبان های طبیعی و … از آن استفاده می کنیم‪.‬‬
‫در شکل زیر لیستی از سمبول ها ساخته ایم‪:‬‬
‫‪17‬‬
‫‪lisp‬‬
‫دوشنبه‪2015/07/20 ،‬‬
‫مهمترین کاربرد در هوش مصنوعی‬
‫‪18‬‬
‫‪lisp‬‬
‫دوشنبه‪2015/07/20 ،‬‬
‫زیرا ‪:‬‬
‫‪19‬‬
‫‪lisp‬‬
‫دوشنبه‪2015/07/20 ،‬‬
‫داده ها‬
‫اشیای داده اولیه ‪:‬‬
‫و‬
‫(‪(S-Expression‬‬
‫اتم در لیسپ به معنای چیزی است که به اجزای کوچکتری تجزیه نمی‬
‫شود‪.‬‬
‫یک اتم در لیسپ می تواند یک نماد یا یک عدد یا رشته اي از کاراکترها‬
‫باشد‪.‬‬
‫اعداد(اتمهای عددی) به شکل صحیح یا ممیز شناور قابل استفاده هستند‬
‫رشته ها به صورت”رشته هایی از نمادها”نمایش داده می شوند‬
‫‪20‬‬
‫‪lisp‬‬
‫دوشنبه‪2015/07/20 ،‬‬
‫لیسپ بین برنامه و داده تمایز قائل نمی شود‬
‫تا طراحی مفسر لیسپ ساده باشد‪.‬‬
‫ترتیب اجرا با فراخوانی تابع و عبارات شرطی مشخص‬
‫می شود‪.‬‬
‫اجرای برنامه لیسپ شامل ارزیابی تابع لیسپ است‪.‬‬
‫‪Read‬‬
‫‪21‬‬
‫مترجم لیسپ تابع است‬
‫‪lisp‬‬
‫دوشنبه‪2015/07/20 ،‬‬
‫اتم و لیست‬
‫‪22‬‬
‫‪lisp‬‬
‫دوشنبه‪2015/07/20 ،‬‬
‫‪23‬‬
‫‪lisp‬‬
‫دوشنبه‪2015/07/20 ،‬‬
‫‪24‬‬
‫‪lisp‬‬
‫دوشنبه‪2015/07/20 ،‬‬
‫‪25‬‬
‫‪lisp‬‬
‫دوشنبه‪2015/07/20 ،‬‬
‫بعضی از توابع آماده در لیسپ‬
‫‪26‬‬
‫‪lisp‬‬
‫دوشنبه‪2015/07/20 ،‬‬
<(append '(1 3 5 7) '(2 4 6 8))
(1 3 5 7 2 4 6 8)
<)cons ‘)a b c( ‘)d e f((
((a b c) d e f)
2015/07/20 ،‫دوشنبه‬
lisp
27
‫‪28‬‬
‫‪lisp‬‬
‫دوشنبه‪2015/07/20 ،‬‬
‫‪29‬‬
‫‪lisp‬‬
‫دوشنبه‪2015/07/20 ،‬‬
‫‪30‬‬
‫‪lisp‬‬
‫دوشنبه‪2015/07/20 ،‬‬
‫‪31‬‬
‫‪lisp‬‬
‫دوشنبه‪2015/07/20 ،‬‬
‫‪32‬‬
‫‪lisp‬‬
‫دوشنبه‪2015/07/20 ،‬‬
‫دستورات کنترلی در لیسپ‬
‫‪33‬‬
‫‪lisp‬‬
‫دوشنبه‪2015/07/20 ،‬‬
‫دستور شرطی ‪if‬‬
‫یک شرط ساده در لیسپ ‪ if‬می باشد‪ .‬این معموال سه آرگومان می گیرد‪ :‬عبارت ‪،test‬‬
‫عبارت ‪ then‬و عبارت ‪ else .‬عبارت ‪ test‬ارزیابی شده در صورتی که مقدار درست‬
‫برگرداند عبارت ‪ then‬ارزیابی می شود‪ .‬در صورتیکه عبارت ‪ test‬مقدار ‪false‬‬
‫برگرداند سپس عبارت ‪ else‬ارزیابی شده و مقدار آن برگردانده می شود ‪.‬‬
‫‪34‬‬
‫‪lisp‬‬
‫دوشنبه‪2015/07/20 ،‬‬
‫تعریف تابع در لیسپ‬
‫‪35‬‬
‫‪lisp‬‬
‫دوشنبه‪2015/07/20 ،‬‬
‫‪36‬‬
‫‪lisp‬‬
‫دوشنبه‪2015/07/20 ،‬‬
‫تعریف تابع جدید‬
‫شما می توانید تابع جدیدي با ‪defun‬تعریف کنید‪ .‬این معموال سه و یا تعداد بیشتري آرگومان‬
‫می گیرد‪ :‬یک نام ‪ ،‬یک لیست از پارامترها و یک یا تعداد بیشتري از عبارات که بدنه ي تابع‬
‫را خواهند ساخت‪ .‬در اینجا توسط تابع ‪ ،‬بدست آوردن سومین عنصر را تعریف می کنیم ‪:‬‬
‫اولین آرگومان می گوید که اسم این تابع ‪our-third‬خواهد بود‪ .‬دومین آرگومان که لیست‬
‫( )‪x‬است می گوید که تابع دقیقا یک آرگومان می گیرد‪X .‬یک سمبول است که به عنوان‬
‫یک نگهدارنده ي مکانی که در اینجا متغیر نامیده می شود می باشد‪ .‬زمانیکه متغیري‬
‫براي نمایش یک آرگومان یک تابع بکار می رود مانند ‪x‬آنرا پارامتر می نامیم ‪ .‬دنباله ي‬
‫تعریف ( )‪car (cdr (cdr x‬به عنوان بدنه ي تابع شناخته شده است‪ .‬این قسمت کاري که‬
‫لسیت براي محاسبه ي مقدار برگشتی تابع انجام می دهد را مشخص می کند‪ .‬بنابراین‬
‫فراخوانی ‪our-third‬برگرداندن ( )‪car (cdr (cdr x‬براي هر مقدار ‪x‬که به عنوان‬
‫آرگومان به آن می دهیم است ‪.‬‬
‫‪37‬‬
‫‪lisp‬‬
‫دوشنبه‪2015/07/20 ،‬‬
‫مثال‪:‬تابعی بنویسید که بررسی کند مجموع دو عدد از عدد سوم بزرگتر است یا خیر؟‬
‫‪38‬‬
‫‪lisp‬‬
‫دوشنبه‪2015/07/20 ،‬‬
‫توابع بازگشتی‬
‫یک تابعی که می تواند خود را فراخوانی کند بازگشتی نام دارد‪ .‬زبان لیسپ تابع را تست‬
‫می کند که آیا عنصر یک لیست می باشد یا خیر ‪ .‬در اینجا یک نمونه ساده از تعریف یک‬
‫تابع بازگشتی وجود دارد ‪:‬‬
‫)‪(defun our-member (obj lst‬‬
‫)‪(if (null lst‬‬
‫‪nil‬‬
‫)‪(if (eql (car lst) obj‬‬
‫‪Lst‬‬
‫)))))‪(our-member obj (cdr lst‬‬
‫‪39‬‬
‫‪lisp‬‬
‫دوشنبه‪2015/07/20 ،‬‬
‫‪ eql‬تساوي دو آرگومان باهم را تست می کند ‪ ،‬گذشته از آن همه چیزي که در این تعریف‬
‫وجود دارد قبال مشاهده شده است‪ .‬در عمل به این صورت است ‪:‬‬
‫((‪> (our-member ’b ’)a b c‬‬
‫)‪(B C‬‬
‫((‪> (our-member ’z’)a b c‬‬
‫‪NIL‬‬
‫در تعریف ‪our-member‬برار بودن حروف بررسی می شود‪ .‬براي تست اینکه هر شی‬
‫‪obj‬یک عضو لیست ‪lst‬می باشد‪ -1 :‬ابتدا بررسی می شود که ‪lst‬خالی است‪ .‬اگر آن خالی‬
‫است آنگاه به وضوح معلوم است که ‪obj‬یک عضو آن نمی باشد و هیچ کاري انجام نمی‬
‫شود ‪ -2 .‬در غیر اینصورت اگر ‪obj‬عنصر اول ‪lst‬باشد‪ .‬آن یک عضو است ‪ -3 .‬در غیر‬
‫اینصورت ‪obj‬تنها یک عضوي از ‪lst‬است اگر آن یک عضو از بقیه ي ‪lst‬باشد‬
‫‪40‬‬
‫‪lisp‬‬
‫دوشنبه‪2015/07/20 ،‬‬
‫تابع خروجی ‪format‬‬
‫‪format‬عمومی ترین تابع خروجی در زبان لیسپ می باشد‪ .‬این تابع دو یا تعداد بیشتري‬
‫آرگومان می گیرد‪ :‬اولی نشان می دهد که خروجی کجا باید چاپ شود ‪ ،‬دومین آرگومان‬
‫نشان دهنده ي قالب رشته می باشد و آرگومانهاي باقیمانده معموال اشیایی هستند که در‬
‫جاهاي مشخص شده در داخل قالب چاپ می شوند‪ .‬دراینجا یک مثال آورده شده ‪:‬‬
‫‪41‬‬
‫‪lisp‬‬
‫دوشنبه‪2015/07/20 ،‬‬
‫تابع ورودی ‪read‬‬
‫‪ read‬تابع استاندارد براي ورودي می باشد‪ .‬زمانی که هیچ آرگومانی داده نمی شود‬
‫این تابع از مکان پیش فرض می خواند ‪ ،‬که معموال سطح باال می باشد‪ .‬در اینجا تابعی‬
‫وجود دارد که از پرامپت ‪ ،‬ورودي کاربر را گرفته و هر آنچه را که گرفته بر می‬
‫گرداند ‪.‬‬
‫‪42‬‬
‫‪lisp‬‬
‫دوشنبه‪2015/07/20 ،‬‬
‫تعریف متغیرهای محلی‬
‫یکی از اپراتورهایی که معموال در لسیپ استفاده می شود ‪let‬است ‪ ،‬که به شما اجازه‬
‫تعریف متغیرهاي محلی جدید را می دهد‬
‫یک عبارت ‪let‬دو بخش دارد‪ .‬ابتدا لیستی از دستورالعمل ها براي ایجاد متغیرها براي‬
‫هر نوع فرمی می آید‪ .‬هر متغیر در ابتدا توسط عبارت نظیر خود مقدار دهی می شوند‪.‬‬
‫همانطور که در مثال باال ما دو متغیر ‪x‬و ‪y‬ایجاد کردیم که به ترتیب با ‪ 1‬و ‪2‬‬
‫مقداردهی اولیه می شوند‪ .‬این متغیر ها در بین بدنه ‪let‬معتبر می باشند ‪ .‬بعد از‬
‫متغیرها و مقادیر بدنه عبارت می آید که براساس قوانین ارزیابی می شوند ‪ ،‬که در‬
‫مورد مثال قبل تنها یکی وجود دارد و آن فراخوانی ‪ +‬است ‪ .‬مقدار آخرین عبارت به‬
‫عنوان مقدار ‪let‬بازگردانده می شود‪.‬‬
‫‪43‬‬
‫‪lisp‬‬
‫دوشنبه‪2015/07/20 ،‬‬
‫تعریف متغیر سراسری‬
‫متغیرهایی که تاکنون دیده ایم متغیرهاي محلی نامیده می شود‪ .‬آنها فقط در یک محدوده ي‬
‫مشخص معتبر می باشند‪ .‬در اینجا نوع دیگري از متغیرها وجود دارد که متغیر سراسري نامیده‬
‫می شود که می تواند در هر کجایی قابل دسترسی باشد ‪ .‬شما با دادن یک سمبول و یک مقدار به‬
‫‪defparameter‬می توانید یک متغیر سراسري ایجاد کنید ‪.‬‬
‫)‪> (defparameter *glob* 99‬‬
‫*‪*GLOB‬‬
‫چنین متغیري در هر جایی قابل دسترسی خواهد بود به جز در عباراتی که متغیر هاي محلی‬
‫جدیدي با همین نام ایجاد شده باشد‪ .‬براي جلوگیري از این اتفاق که بصورت تصادفی رخ می‬
‫دهد ابتدا و انتهاي نام متغیرهاي سراسري را با عالمت * نشان می دهند‪ .‬نام متغیري که ما ایجاد‬
‫ک دیر م""‪star-glob-star‬تلفظ می شود ‪ .‬شما می توانید با فراخوانی ‪defconstant‬ثابت هاي‬
‫سراسري تعریف کنید‪.‬‬
‫))‪<(defconstant limit (+ *glob* 1‬‬
‫در اینجا نیازي نیست که به ثابتها نام متمایز داده شود چرا که هرکسی که بخواهد از این نام براي‬
‫تعریف متغیرها استفاده کند خطا ایجاد خواهد کرد‪ .‬اگر شما بخواهید بررسی کنید که هر سمبول‬
‫یک متغیر سراسري و یا یک ثابت است از ‪boundp‬استفاده می کنیم‪.‬‬
‫)*‪< (boundp '*glob‬‬
‫دوشنبه‪T 2015/07/20 ،‬‬
‫‪lisp‬‬
‫‪44‬‬
‫انتساب‬
‫در زبان لیسپ به طور کلی از اپراتور ‪setf‬براي انتساب استفاده می شود‪ .‬ما می توانیم براي‬
‫انتساب هر نوع متغیري از آن استفاده کنیم ‪.‬‬
‫)‪<(setf *glob* 98‬‬
‫‪98‬‬
‫))‪> (let ((n 10‬‬
‫)‪(setf n 2‬‬
‫)‪n‬‬
‫‪2‬‬
‫‪‬زمانی که اولین آرگومان به ‪setf‬داده می شود یک سمبولی که نام آن یک متغیر محلی نمی‬
‫باشد به عنوان یک متغیر سراسري گرفته می شود ‪.‬‬
‫))‪>(setf x (list 'a 'b 'c‬‬
‫)‪(A B C‬‬
‫‪45‬‬
‫‪lisp‬‬
‫دوشنبه‪2015/07/20 ،‬‬
‫ فاکتوریل‬: ‫بازگشتی‬
<(defun fact (n)
(if (= n 0)
0
(if (= n 1)
1
(* n (fact (- n 1))))))
FACT
<(fact 3)
6
<(fact 0)
ERROR
2015/07/20 ،‫دوشنبه‬
lisp
46
‫ سری فیبوناچی‬: ‫بازگشتی‬
0 1 1 2 3 5 8…
<(defun fibo (n)
(if ( = n 0)
0
(if (= n 1)
1
(+ (fibo (- n 1)) (fibo (- n 2))))))
FIBO
<(fibo 0)
0
<(fibo 4)
3
2015/07/20 ،‫دوشنبه‬
lisp
47
‫ مجموع اعداد یک لیست‬: ‫بازگشتی‬
>(defun sum-list (numbers)
(if (null numbers)
0
(+ (first numbers) (sum-list (cdr numbers)))))
>(sum-list ‘)2 4 6 8))
20
2015/07/20 ،‫دوشنبه‬
lisp
48
‫ دوبرابر کردن اعداد یک لیست‬: ‫بازگشتی‬
<(defun double-list (numbers)
(if (null numbers)
nil
(cons (* 2 (first numbers)) (double-list (cdr numbers)))))
DOUBLE-LIST
<(double-list '(1 2 3 4))
(2 4 6 8)
2015/07/20 ،‫دوشنبه‬
lisp
49
:‫مثال‬
<(defun teenager (age)
(if (and (> age 12) (< age 20))
"Teenager"
"Not teenager"))
<(append '(1 3 5 7) '(2 4 6 8))
(1 3 5 7 2 4 6 8)
<)cons ‘)a b c( ‘)d e f((
((a b c) d e f)
2015/07/20 ،‫دوشنبه‬
lisp
50
‫کار به رشته‬
‫‪51‬‬
‫‪lisp‬‬
‫دوشنبه‪2015/07/20 ،‬‬
Finding the length of a string: length
‫کار با رشته ها‬
Reversing a string: reverse
Joining two (or more) strings
together: concatenate
Getting a subsequence from a string:
subseq
2015/07/20 ،‫دوشنبه‬
lisp
52
‫‪53‬‬
‫‪lisp‬‬
‫دوشنبه‪2015/07/20 ،‬‬
‫‪54‬‬
‫‪lisp‬‬
‫دوشنبه‪2015/07/20 ،‬‬