بالا
 تعرفه تبلیغات




 دانلود نمونه سوالات نیمسال دوم 93-94 پیام نور

 دانلود نمونه سوالات آزمونهای مختلف فراگیر پیام نور

صفحه 1 از 2 12 آخرینآخرین
نمایش نتایج: از شماره 1 تا 10 از مجموع 13

موضوع: زبان های برنامه نویسی در روباتیک

  1. #1
    TAHA آواتار ها
    • 9,180
    مدير بازنشسته

    عنوان کاربری
    مدير بازنشسته
    تاریخ عضویت
    Mar 2009
    محل تحصیل
    PNU-CLUB
    شغل , تخصص
    PNU-CLUB
    رشته تحصیلی
    PNU-CLUB
    راه های ارتباطی

    Icon300 زبان های برنامه نویسی در روباتیک

    عناوین متن
    زبانهای برنامه‌نویسیAI، برنامه‌نویسی تابعی ، برنامه‌نویسی تابعی در Lisp ، A- Syntax (نحو) و semantic های (معانی) Lisp ، لیست انواع داده ، تعریف توابع جدید ، تعریف ساختارهای كنترلی ، تعریف توابع بازگشتی ، توابع مرتبه بالا ، سایر زبانهای برنامه‌نویسی تابعی غیر از Lisp ، برنامه‌نویسی منطقی در Prolog ، سایر روشهای برنامه‌نویسی

    واژه نامه
    بندهای برنامه Prolog
    شامل مجموعه‌ای از جملات بنام بندها هستند كه برای نشان دادن داده‌ها و برنامه‌ها بكار می‌روند.
    تابع مرتبه بالا تعریف تابعی است كه اجازه می‌دهد آرگومانها یا مقدار بازگشتی تابع، مقدار توابع باشد. نماد ساختار لیستها اغلب نشان‌دهنده نحوه استفاده از لیست ساختاری داده هستند، كه یك عنصر لیست ممكن است نماد یا لیست دیگر باشد. لیستها ساختاری مركزی Lisp هستند كه برای نشان دادن داده‌ها و برنامه‌ها بكار می‌روند. بازگشت تكنیكی الگوریتمی برای انجام یك كار است كه یك تابع با بعضی از قسمتهای كار خودش را فراخوانی می‌كند.
    محاسبات نمادین برنامه‌نویسی AI (اساساً) شامل دستكاری نمادها است نه اعداد. این نمادها می‌توانند اشیاء در جهان و ارتباط بین آن اشیاء را نشان دهند- ساختارهای پیچیده نمادها نیاز به دانش ما از جهان دارند. واژه ساختار اساسی داده‌ها در Prolog واژه‌ای است كه می‌تواند یك ثابت، یك متغیر یا یك ساختار باشد. ساختارها موضوعات ریز محاسبات گزاره‌ای را نشان می‌دهند و شامل یك عملگر نام و یك پارامتر لیست هستند.
    زبانهای برنامه‌نویسی هوش مصنوعی(AI) ابزار اصلی بررسی و ساخت برنامه‌های كامپیوتری هستند كه می‌توانند در شبیه‌سازی فرایندهای هوشمند مانند یادگیری،‌ استدلال و فهم اطلاعات نمادین بكار بروند. هر چند اخیراً زبان كامپیوتر اصولاً برای استفاده از كامپیوترها برای انجام محاسبات با اعداد طراحی شده بود، اما بزودی دریافتند كه رشته‌ای از بیتها نه تنها اعداد بلكه می‌توانند اشیای دلخواه را نیز نمایش دهند. عملیات روی ویژه‌گی‌ها یا نمادها می‌تواند با استفاده از قوانین برای ایجاد، انتساب یا دستكاری نشان داده شود. این تصور از محاسبات نمادین بعنوان تعریف الگوریتمهایی كه هر نوع اطلاعات را پردازش می‌كنند و بنابراین می‌تواند برای شبیه‌سازی هوش انسان بكار برود مناسب است.
    بزودی برنامه نویسی با نمادها كه نیاز به سطح بالایی از چكیدگی دارند تولید می‌شوند، غیر از امكاناتی كه با زبانهای برنامه نویسی مخصوص پردازش اعداد ممكن بود مانند فرترن

  2. #2
    TAHA آواتار ها
    • 9,180
    مدير بازنشسته

    عنوان کاربری
    مدير بازنشسته
    تاریخ عضویت
    Mar 2009
    محل تحصیل
    PNU-CLUB
    شغل , تخصص
    PNU-CLUB
    رشته تحصیلی
    PNU-CLUB
    راه های ارتباطی

    پیش فرض

    I-زبانهای برنامه نویسی AI
    در AI خودكار كردن یا برنامه‌نویسی همه جنبه‌های شناخت انسانی بوسیله بنیادهای شناخت علمی روشهای نمادین و غیر نمادین AI، پردازش زبان طبیعی، دید كامپیوتری و سیستمهای تكامل یا سازگار مطرح می‌شود. لازم است دامنه مسئله‌های خیلی پیچیده در ابتدای مرحله برنامه‌نویسی یك مسئله AI معین، مشخص شود كه كافی نیست. تنها بوسیله تعامل و افزایش اصلاحات خصوصیات بسیار دقیق ممكن است. در حقیقت مسئله‌های معمول AI به بسیاری از زمینه‌های خاص گرایش دارند، بنابراین روشهای ذهنی باید بوسیله تولید و آزمایش روشها بطور تجربی توسعه یابند(مشهور به نمونه سازی سریع). در اینصورت برنامه‌نویسی AI بطور قابل توجهی با روشهای استاندارد مهندسی نرم‌افزار متفاوت بوده زیرا برنامه‌نویسی معمولا از یك مشخصات رسمی با جزئیات شروع می‌شود. در برنامه‌نویسی AI پیاده‌سازی در واقع جزئی از پردازش مشخصات مسئله است. به اقتضای طبیعت مسئله‌های AI برنامه‌نویسی AI مزایای بسیاری دارد اگر زبانهای برنامه نویسی، برنامه‌نویسAI را آزاد بگذارند و در بسیاری از ساختارهای فنی محدود نكنند (مانند ساختار انواع داده‌ای جدید سطح پایین، دستیابی دستی به حافظه). ترجیحاً سبك برنامه‌نویسی اعلانی برای استفاده در ساختارهای پیش‌ساخته داده‌ای سطح بالا(مانند لیستها و درختها) و عملیات(مانند تطبیق الگوها) مناسب است، بنابراین محاسبات نمادین سطح خلاصه‌سازی بیشتری نسبت به آنچه كه با زبانهای دستوری استاندارد مانند فرترن، پاسكال یا C امكان‌پذیر خواهد بود را پشتیبانی می‌كند. البته طبقه‌بندی خلاصه سازی آسان نیست،‌ زیرا تدوین برنامه‌های AI روی كامپیوترهای استاندارد وان نیومن نمی‌تواند به كارآمدی زبانهای دستوری باشد. هر چند یك مسئله مسلم AI فهم آن است (حداقل جزئیات) امكان دارد با تنظیم مجدد آن به شكل خصوصیات جزئی شده با بكار بردن یك زبان دستوری پیاده‌ سازی مجدد شود. با توجه به نیازمندیهای محاسبات نمادین و برنامه‌نویسی AI دو الگوی جدید برنامه‌نویسی كه به سبك دستوری پیشنهاد می‌شوند بوجود می‌‌آید: سبك برنامه‌نویسی تابعی و منطقی. هر دو بر مبنای ریاضیات طرح‌ریزی شده‌اند، یعنی نظریه توابع بازگشتی و منطق رسمی. اولین زبان برنامه‌نویسی AI كاربردی كه هنوز هم بطور گسترده استفاده می‌شود زبان برنامه‌نویسی Lisp است كه در اواخر دهه 1950 توسط جان مك كارتی توسعه یافته است. Lisp برمبنای نظریه توابع ریاضی و خلاصه‌سازی Lambda است. تعدادی از كاربردهای مهم و موثرAI در Lisp نوشته شده است. كه ما بعضی از جزئیات این زبان برنامه‌نویسی را در این مقاله شرح خواهیم داد. در اوایل دهه 1970 یك الگوی برنامه‌نویسی جدید بنام برنامه‌نویسی منطقی بر اساس محاسبات گزاره‌ای بوجود آمد. اولین و مهمترین زبان برنامه‌نویسی منطقی Prolog است كه توسط آلن كالمرار، رابرت كوالسكی و فیلیپ راسل توسعه یافته است. مسئله‌ها در prolog بصورت حقایق، بدیهیات و قوانین منطقی برای استنباط حقایق جدید بیان می‌شوند. Prolog با قانون ریاضی در محاسبات گزاره‌ای و نتایج نظری بدست آمده در زمینه اثبات قضیه خودكار در اواخر دهه 1960 بنا نهاده شده است.

  3. #3
    TAHA آواتار ها
    • 9,180
    مدير بازنشسته

    عنوان کاربری
    مدير بازنشسته
    تاریخ عضویت
    Mar 2009
    محل تحصیل
    PNU-CLUB
    شغل , تخصص
    PNU-CLUB
    رشته تحصیلی
    PNU-CLUB
    راه های ارتباطی

    پیش فرض

    II- برنامه نویسی تابعی
    یك تابع ریاضی نگاشتی از یك مجموعه (دامنه) به مجموعه دیگر(برد) است. تعریف یك تابع توصیف این نگاشت است كه یا بطور صریح بوسیله شمارش و یا بطور ضمنی بوسیله یك عبارت است. تعریف یك تابع بوسیله نام تابع كه بدنبال آن لیستی از پارامترها در داخل پرانتز قرار دارند و به دنبال آن نیز عبارت توصیفی نگاشت است مشخص می شود مانند:
    X یك عدد حقیقی است cube(X) ≡ X X X , where X is a real number.
    آلونسو چارچ توابع بی نام را با استفاده از نمادLambda معرفی می كند. یك عبارت Lambda پارامترها و نگاشت تابع را با استفاده از عملگر X مشخص می كند, مانند λ (X)X X X آن خودش تابع است, بنابراین شرح بكار رفته در مثال تابع بی نام با یك آرگومان مشخص است. برای مثال:(λ (X) X X X)(4).
    برنامه نویسی در یك زبان تابعی شامل ساختمان تعریف توابع و بكاربردن كامپیوتر برای ارزیابی عبارات است. یعنی بكاربردن توابع با آرگومانهای واقعی. كار اصلی برنامه نویسی پس از ساخت یك تابع برای یك مساله خاص تركیب توابع تعریف شده قبلی با توجه به اصول ریاضی است. كار اصلی كامپیوتر ارزیابی توابع فراخوانی شده و چاپ حاصل مقادیر تابع است. در این روش كامپیوتر مشابه یك كامپیوتر جیبی معمولی بكار می رود البته بسیار انعطاف پذیرتر و قدرتمندتر. یك خاصیت برنامه نویسی تابعی این است كه اگر عبارت به خوبی مقداردهی شود آنگاه ترتیب انجام ارزیابی كامپیوتر در نتایج ارزیابی تاثیری ندارد. بنابراین نتیجه ارزیابی یك عبارت تنها مقدار آن است. بدین معنی است كه در یك زبان تابعی ناب اثرات جانبی وجود ندارد. اثرات جانبی در مدل موقعیت های حافظه به متغیرها متصل شده اند.بنابراین در یك زبان برنامه نویسی ناب در مفهوم زبانهای دستوری متغیر وجود ندارد. روشهای اصلی كنترل جریان، بازگشت (تكرار) و عبارات شرطی هستند. این كاملاً با زبانهای دستوری در مفهوم اساسی كنترل ترتیب و تكرار متفاوت است. برنامه نویسی تابعی نیز خصوصیات توابع مرتبه بالا را پشتیبانی می كند. تابع مرتبه بالا تعریف تابعی است كه اجازه می دهد آرگومانها یا مقدار بازگشتی تابع, مقدار توابع باشند. همه این جوانب با هم مخصوصاً آخری از اصلی ترین مزایای سبك برنامه نویسی تابعی در برابر سبك برنامه نویسی دستوری هستند. خلاصه برنامه نویسی تابعی سطح بالایی از درجه پیمانه ای بودن را فراهم می كند. وقتی یك مسئله با تقسیم آن به مجموعه ای از زیر مسئله ها تعریف می شود, موضوع اصلی روشهایی است كه می توان زیر مسئله ها را به یكدیگر چسباند. بنابراین برای افزایش قابلیت پیمانه ای بودن یك مسئله مفهومی, ابتدا باید نوع جدیدی از چسب در زبان برنامه نویسی فراهم شود- قدرت اصلی برنامه نویسی تابعی .

  4. #4
    TAHA آواتار ها
    • 9,180
    مدير بازنشسته

    عنوان کاربری
    مدير بازنشسته
    تاریخ عضویت
    Mar 2009
    محل تحصیل
    PNU-CLUB
    شغل , تخصص
    PNU-CLUB
    رشته تحصیلی
    PNU-CLUB
    راه های ارتباطی

    پیش فرض

    III- برنامه نویسی تابعی در Lisp
    Lisp اولین زبان برنامه نویسی تابعی است: آن برای پشتیبانی محاسبات نمادین با استفاده از لیستهای پیوندی بعنوان ساختار مركزی داده ها ابداع شده بود ( Lisp یعنی پردازشگر لیست). جان مك كارتی دریافت كه روشهای كنترل جریان توابع ریاضی (بازگشت و تكرار) وسیله نظری مناسبی برای انجام محاسبات نمادین هستند. علاوه براین مفاهیم خلاصه سازی تابعی و كاربرد تابعی تعریف شده در محاسبات Lambda , سطح بالایی از خلاصه سازی موردنیاز برای مسئله های AI مشخص شده را فراهم می كنند.
    Lisp در سال 1958 توسط مك كارتی ابداع شد و اولین نگارش محیط برنامه نویسی Lisp در سال 1960 آماده شد كه شامل یك مفسر, یك كامپایلر و مكانیسم تخصیص و بازپسگیری حافظه پویا بود (بعنوان مجموعه فضای هرز شناخته شده است). یكسال بعد اولین زبان استاندارد با نام Lisp1.5 معرفی شد. پس از آن تعدادی از نسخه ها و محیط های برنامه نویسی Lisp توسعه یافته اند. مانند MacLisp، FranzLisp، InterLisp، CommonLisp، Scheme هر چند آنها در بعضی جزئیات خاص متفاوتند ولی هسته Syntax (نحو) و Semantic (معنی) آنها اساساً یكسان است. هسته را در جای دیگر معرفی خواهیم كرد. پر استفاده ترین نسخه‌های
    Lisp ، Common Lisp و scheme هستند. در این مقاله ما Common Lisp را برای نشان دادن جنبه های مختلف Lisp با مثالهای معمولی انتخاب كرده ایم. هرچند مثالها نیز به راحتی می توانند در نسخه های دیگر Lisp سازگار شوند.

  5. #5
    TAHA آواتار ها
    • 9,180
    مدير بازنشسته

    عنوان کاربری
    مدير بازنشسته
    تاریخ عضویت
    Mar 2009
    محل تحصیل
    PNU-CLUB
    شغل , تخصص
    PNU-CLUB
    رشته تحصیلی
    PNU-CLUB
    راه های ارتباطی

    پیش فرض


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

    (if (eq elem (first list)) T

    (member elem (rest list))))
    توضیح اینكه در بسیاری از مثالها عناصر لیست خود لیستها هستند.چنین لیستهایی، لیستهای تو در تو نامیده می‌شوند. در مورد تو در تویی محدودیتی وجود ندارد. برای مثال یكی از قویترین Lisp ها را شرح می‌دهیم: پیچیده‌ترین اشیاء را به راحتی می‌توان نوشت. تنها چیزی كه در نظر گرفته می‌شود درستی عدد داخل پرانتزهاست. مهم توضیح این است كه معنی وابسته به یك لیست نمایش ویژه یا اتم در لیست نمایش وارد نمی‌شود. به این معنی كه همه عبارات نمادین كه در بالا توصیف شده است از لحاظ نحو برنامه‌های Lisp را اصلاح می‌كنند ولی الزاماً از لحاظ معنی (semantic) برنامه‌ها رااصلاح نمی‌كنند.
    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 اجرا شود حلقه خواندن- محاسبه- چاپ فعال خواهد بود.
    عبارت نمادین ( 4 3 + ) كه بوسیله هكر Lisp وارد شده است بوسیله مفسر Lisp بصورت فراخوانی تابع جمع تفسیر شده و نتیجه عبارت نمادین در ابتدای خط جدید 7 چاپ می‌‌شود ارزیابی مفسر Lisp مطابق سه قانون زیر انجام می‌‌شود:
    1- یكسانی: یك عدد،‌ یك رشته یا نمادهای t و nil خودشان را ارزیابی می‌كنند (بر می‌گردانند) به این معنی كه ارزش عدد 3،3 و ارزش رشته ”house”، رشته ”house”است. نمادt مقدار t برمی‌گرداند كه به معنای true تفسیر می‌شود وnil ، 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
    در اینجا آرگومانها 5, 7, (min 9 8), 4 هستند كه در اولویتی قبل از تابعی به نام max كه نتیجه مقادیر آرگومانها را به كار می‌برد ارزیابی می‌شوند. آرگومان اول 4 ،‌ یك عدد است پس مقدار آن 4 است. آرگومان دوم (min 9 8) است كه خودش یك فراخوانی تابع است. بنابراین باید قبل از آرگومان سوم فراخوانی شود، (min 9 8) باید توسط مفسر Lisp ارزیابی شود. چون ما باید مفسر Lispرا برای بعضی آرگومانها در طول ارزیابی همه فراخوانی‌های توابع استفاده كنیم می‌‌توان گفت مفسر Lisp بصورت بازگشتی فراخوانی شده است. مفسر Lisp همان مراحل را به كار می‌برد، پس آرگومان اول 9 قبل از آرگومان دوم 8، ارزیابی می‌شود. با بكار برروی تابع min حاصل 8 می‌شود یعنی تابع كوچكترین عدد یك مجموعه از اعداد صحیح را محاسبه می‌‌كند. برای تابع بیرونی max هم به این معنی است كه آرگومان دوم آن 8 ارزیابی می‌شود.
    آرگومانهای بعدی 7و5هستند كه نتیجه ارزیابی آنها مقادیر 7و5 می‌شود. حال تابع بزرگترین عدد كه max نام دارد می‌تواند ارزیابی شود كه 8 برمی‌گرداند. این مقدار نهایی،‌ مقدار فراخوانی همه توابع می‌‌باشد. از آنجایی كه گفته می‌‌‌شود مفسر Lisp همیشه سعی می‌كند مقدار یك نماد یا تفسیر یك لیست بعنوان یك فراخوانی تابع را تشخیص دهد ما چگونه می‌توانیم با نمادها و لیستها بعنوان داده رفتار كنیم؟ برای مثال، اگر ما لیست (peter walks home) را وارد كنیم، آنگاه مفسر Lisp فوراً یك خطا می‌دهد كه چیزی شبیه این خطا می‌گوید: تابع peter ناشناخته است (مفسرLisp باید بقدری باهوش باشد كه بتواند ابتدا كنترل كند كه آیا تعریف تابعی برای نام تابع تعیین شده وجود دارد یا نه، قبل از اینكه هر آرماگونی را ارزیابی كند). یا اگر ما فقط house را وارد كنیم، آنگاه مفسر Lisp با خطایی شبیه این خطا خاتمه می‌یابد: مقداری به house متصل نیست (تخصیص نیافته است). حل این مسئله كاملاً آسان است. زیرا عنصر اصلی هر لیست بعنوان نام تابع تفسیر می‌شود،‌هر سیستم Lisp با یك تابع پیش‌ساخته quote می‌‌آید كه یك عبارت نمادین را بعنوان آرگومان پذیرفته و این عبارت نمادین را بدون ارزیابی آن برمی‌گرداند. برای مثال: لیست(quote(peter walks home)) ، به سادگی مقدار
    (peter walks home) را برمی‌گرداند، و برای (quote house)، آن house را بر می‌‌گرداند. از آنجایی كه تابع quote زیاد استفاده می‌‌‌شود، می‌توان آن را با كاراكتر ویژه ' بیان كرد. بنابراین برای مثال بالا می‌توانیم معادل’(Peter walks home) و’house را مشخص كنیم. برنامه‌ها بعنوان داده، یعنی تابع quote به ما امكان می‌‌‌دهد تا با فراخوانی تابع بعنوان داده رفتار كنیم. برای مثال: (quote (max 4 (min 9 8) 7 5)) یا ’(max 4 (min 9 8) 7 5)
    قبلاً گفتیم كه مفسر Lisp یك تابع یكتایی پیش‌ساخته است كه eval نام دارد. آن صریحاً آرگومانهایش را وادار می‌كند تا مطابق قوانین مذكور در بالا ارزیابی شوند. در بعضی حالات، آن می‌تواند مقابل تابع quote قرار بگیرد بنابراین به وضوح لازم است كه یك لیست بعنوان داده مشخص شود تا سیستم Lisp بتواند یك فراخوانی تابع تفسیر شود، ما می‌توانیم(eval ’(max 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

    ?(setq max (max 3 2 5 1))
    3
    توضیح اینكه در واقع Setq حالت مفسر Lisp را تغییر می‌دهد تا دفعه بعدی كه همان متغیر استفاده می‌شود، دارای مقدار بوده و بنابراین مفسرLisp قادر به بازگرداندن آن خواهد بود. اگر این اتفاق نیفتد آنگاه مفسر Lisp یك اخطار خواهد داد زیرا نماد متصل نشده است.
    (گام 2 مفسر Lisp پیدا نشد). بنابراین آن می‌گویدكه Setq یك اثر جانبی تولید می‌كند زیرا حالت مفسر Lisp بطور پویا تغییر می‌دهد. وقتی استفاده از Setq اجباری شد، به هرحال متوجه شد كه در واقع از مسیر semantics (معانی) Lisp ناب دور می‌شود. پس Setq باید با دقت بسیار استفاده شود.

  6. #6
    TAHA آواتار ها
    • 9,180
    مدير بازنشسته

    عنوان کاربری
    مدير بازنشسته
    تاریخ عضویت
    Mar 2009
    محل تحصیل
    PNU-CLUB
    شغل , تخصص
    PNU-CLUB
    رشته تحصیلی
    PNU-CLUB
    راه های ارتباطی

    پیش فرض

    B. نوع داده لیست
    برنامه‌نویسی در Lisp در واقع به معنی تعریف توابعی است كه روی لیست عمل می‌كنند. مانند ایجاد، پیمایش،‌كپی، تغییر و حذف لیستها. از آنجایی كه این در Lisp مركزی است، هر سیستم Lisp بر مبنای مجموعه‌ای از توابع پیش‌ساخته ابتدایی كه بطور موثری عملیات اصلی لیست را پشتیبانی می‌كند می‌آید. ما بطور خلاصه یكی از مهمترین آنها معرفی می‌كنیم. ابتدا نوع گزاره‌ای،‌ ما می‌دانیم كه یك عبارت نمادین جاری یا یك لیست است یا نیست (یعنی یك اتم). این كار بوسیله تابع Listp انجام می‌شود كه هر عبارت نمادین 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 ابتدا عبارت
    (cdr ’(see the quote))را ارزیابی خواهد كرد كه لیست (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 نیست. یك توضیح كوتاه تاریخی: نامهای Car,cdr از روشهای قدیمی هستند زیرا آنها در اولین نگارش Lisp كه بر مبنای مجموعه عملیات كد ماشین كامپیوتر انتخاب و پیاده سازی شده بودند (car از محتوای ثبات آدرس استفاده می‌كند و cdr از محتوای ثبات كاهش استفاده می‌كند). به منظور نوشتن كد Lisp خواناتر، common Lisp یا در تابع first و rest بوجود آمد. ما نامهای قدیمی را استفاده می‌كنیم تا برای خواندن و فهم كد AI Lisp قدیمی قادر باشیم. برای ساخت لیستها، یك تابع ابتدایی 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 (list 1) 2 (list 1 2 3)) ==>((1) 2 (1 2 3))

    (append ’(1) (list 2)) ==>(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
    __________________

  7. #7
    TAHA آواتار ها
    • 9,180
    مدير بازنشسته

    عنوان کاربری
    مدير بازنشسته
    تاریخ عضویت
    Mar 2009
    محل تحصیل
    PNU-CLUB
    شغل , تخصص
    PNU-CLUB
    رشته تحصیلی
    PNU-CLUB
    راه های ارتباطی

    پیش فرض

    C. تعریف توابع جدید
    برنامه‌نوسی در 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 است(3 همان عدد3 است كه خودش را ارزیابی كرده است) به پارامترx متصل می‌كند. سپس مقدار آرگومان دوم كه 5 است به پارامترy متصل می‌شود. چون مقدار یك آرگومان به یك پارامتر متصل می‌شود، این روش فراخوانی با مقدار نامیده شده است. بعد از مقدار‌یابی برای همه پارامترها مفسرLisp قادر به ارزیابی بدنه تابع خواهد بود. مثال بدین معنی است كه ( 3 5 +) فراخوانی خواهد شد. نتیجه فراخوانی8 است كه بعنوان نتیجه فراخوانی(my-sum 3 5) برگردانده می‌شود. بعد از تكمیل فرا‌خوانی تابع اتصالات موقت پارامترهایx وy حذف می‌شوند. هنگامی كه یك تعریف تابع جدید در سیستمLisp وارد می‌شودمی‌تواند به عنوان جزئی از تعریف تابع جدید به همان روش كه بعنوان تابع پیش ساخته استفاده شده است بكار برده شود بطوریكه در مثال زیر نشان داده شده است.
    (defun double-sum (x y)

    (+ (my-sum x y) (my-sum x y)))
    كه با دوبار فراخوانیmy-sum جمع آرگومانهایش را دو برابر خواهد كرد این مثال دیگری از یك تعریف تابع است نشان دادن استفاده از عبارات نمادین چند‌گانه در بدنه تابع است.
    (defun hello-world () (print ”Hello World!”) ’done)

    این تعریف تابع پارامتری ندارد زیرا لیست پارامتر آن خالی است بنابراین وقتی(hello-world) فراخوانی می‌شود مفسرLisp بلافاصله (print ”Hello World!”) را ارزیابی و رشته
    ”Hello World!”را روی نمایشگر شما بعنوان یك اثر جانبی چاپ می‌كند سپس نماد’done را ارزیابی خواهد كرد وdone را به عنوان نتیجه فراخوانی تابع برمی‌گرداند.

  8. #8
    TAHA آواتار ها
    • 9,180
    مدير بازنشسته

    عنوان کاربری
    مدير بازنشسته
    تاریخ عضویت
    Mar 2009
    محل تحصیل
    PNU-CLUB
    شغل , تخصص
    PNU-CLUB
    رشته تحصیلی
    PNU-CLUB
    راه های ارتباطی

    پیش فرض

    D. تعریف ساختارهای كنترلی
    هر چنداكنون تعریف توابع جدید با تعریف توابع پیش ساخته و توابعی كه كاربر تعریف می‌كند ممكن است برنامه‌نویسی درLisp بسیار خسته كننده خواهد شداگر كنترل جریان اطلاعات بوسیله شاخه‌های شرطی ممكن نبود شاید بارها تكرار می‌شد تا اینكه یك روند توقف اجرا شود گزینشLisp بر مبنای ارزیابی توابع است توابع كنترل تستهایی روی عبارات نمادین واقعی انجام می‌دهد و ارزیابی عبارات نمادین متناوب را بسته به نتایج انتخاب می‌كنند تابع اساسی برای تعیین اثباتهای شرطی درcond،Lisp است.cond تعداد دلخواهی آرگومان رامی‌پذیرد هر آرگومان یك بخش ممكن را بیان می‌كنند و بعنوان یك لیست نمایش داده شده كه عنصر اول یك تست و بقیه عناصر اعمال (عبارات نمادین) هستند كه اگر تست انجام شود ارزیابی می‌شوند مقدار آخرین عمل به عنوان مقدار پیشنهادی برگردانده می‌شود همه آرگومانهای ممكنcond (یعنی بخشها) تا زمانی كه بخش اول بطور مثبت تست شوداز چپ به راست ارزیابی می‌شوند درآن حالت مقدار آن بخش مقدار كل تابعcond است. در واقع این مفهوم بسیار پیچیده تر از آن است اجازه دهید تابعverbalize-prop زیركه یك مقدار احتمال را بیان می‌كند. به عنوان یك عدد حقیقی فرض می‌كنیم.
    (defun verbalize–prop (prob-value)

    (cond ((> prob–value 0.75) ’very-probable)

    ((> prob–value 0.5) ’probable)

    ((> prob–value 0.25) ’improbable)

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

  9. #9
    TAHA آواتار ها
    • 9,180
    مدير بازنشسته

    عنوان کاربری
    مدير بازنشسته
    تاریخ عضویت
    Mar 2009
    محل تحصیل
    PNU-CLUB
    شغل , تخصص
    PNU-CLUB
    رشته تحصیلی
    PNU-CLUB
    راه های ارتباطی

    پیش فرض

    E. تعریف توابع بازگشتی
    دومین روش اصلی برای تعریف كنترل جریان درLisp تعاریف توابع بازگشتی هستند. تابعی كه از تعریفش بعنوان جزئی از تعریفش استفاده می‌كند باز‌گشتی نام دارد. بنابراین، یك تعریف بازگشتی، تا جایی كه امكان دارد مسئله‌ای را به قسمتهای كوچكتر تقسیم می‌كند سپس این قسمتهای كوچكتر را با استفاده از توابع مشهور و جمع پاسخهای یكسان حل كرده و حل برنامه را كامل می‌كند. بازگشت یك روش طبیعی برای كنترل ساختارهای داده‌ای است كه اندازه معینی ندارد. مانند لیستها، درختها و گرافها. بنابراین برای مسئله‌هایی كه در یك فاصله از حالات دنبال حل كاندید می‌گردند مناسب است.
    Lisp اولین زبان برنامه‌نویسی كاربردی بود كه با روش معین تعریف تعاریف بازگشتی را پشتیبانی كرده است. ما از دو مثال كوچك برای نشان دادن بازگشت درLisp استفاده خواهیم كرد. اولین مثال برای تعیین طول یك لیست طویل دلخواه استفاده می‌شود. طول یك لیست برابر تعداد عناصر آن است. تابع بازگشتی آن به صورت زیر است.
    (defun length (list)

    (cond ((null list) 0)

    (T (+ 1 (length (cdr list))))))
    وقتی یك تعریف بازگشتی تعریف می‌شود. ما باید حالتهای اساسی راشناسایی كنیم یعنی آن قسمتهایی كه نمی‌توانند بیشتر تجزیه شوند. مسئله اندازه وابسته به لیست است. كوچكترین مسئله اندازه در لیست، لیست خالی است. بنابراین اولین چیزی كه ما باید مشخص كنیم تستی برای شناسایی لیست خالی است و تعیین اینكه طول لیست خالی باید چقدر باشد تابع پیش‌ساخته null تست می‌كند كه آیا این لیست خالی است در این صورت t برمی‌گرداند. از آنجایی كه لیست خالی بدون عنصر است تعریف می‌كنیم كه طول لیست خالی صفر باشد كار دیگری كه باید انجام شود تجزیه مسئله اندازه به قسمتهای كوچكتر است كه همان مسئله می‌تواند برای فسمتهای كوچكتر استفاده شود. تجزیه لیست می‌تواند با استفاده از توابع cdr,car انجام شود. به این معنی كه ما باید تعیین كنیم تا وقتی كه لیست خالی پیدا شود عنصر اول و بقیه عناصر لیست چه كار بكنند. از آنجایی كه ما ازقبل لیست خالی را بعنوان حالت اساسی شناسایی كردیم، می‌توانیم فرض كنیم تجزیه برروی لیستی شامل حداقل یك عنصر انجام خواهد شد. بنابراین هر بار كه قادر خواهیم بود تا با بكار بردن 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)))))

  10. #10
    TAHA آواتار ها
    • 9,180
    مدير بازنشسته

    عنوان کاربری
    مدير بازنشسته
    تاریخ عضویت
    Mar 2009
    محل تحصیل
    PNU-CLUB
    شغل , تخصص
    PNU-CLUB
    رشته تحصیلی
    PNU-CLUB
    راه های ارتباطی

    پیش فرض

    F. توابع مرتبه بالا
    درLisp توابع می‌توانند بعنوان آرگومان استفاده شود تابعی كه بتواند توابع را بعنوان آرگومانهایش بپذیرد تابع مرتبه بالا نامیده می‌شود. مشكلات فراوانی وجود دارند كه یكی پیمایش یك لیست(یا یك درخت یا یك گراف) است كه باید برای هر لیست عنصر تابع معینی استفاده شود. برای مثالfilter تابعی است كه تستی برای عناصر لیست به‌كار می‌برد و آنهایی كه شكست می‌خورند را حذف می‌كند. نگاشتها توابعی هستند كه همان تابع را روی هر عنصر لیست به كار می‌برند تا لیستی از نتایج را برگردانند. تعاربف توابع مرتبه بالا می‌تواند برای تعریف توابع عمومی پیمایش لیست استفاده شود كه آنها از توابع خاصی كه برای پردازش عناصر لیست بكار می‌روند خلاصه می‌شوند (چكیده می‌شوند). به منظور پشتیبانی تعاریف مرتبه بالا یك تابع خاص است كه یك تابع و دنباله‌ای از آرگومانها را به عنوان آرگومان می‌پذیرد و آن تابع را در آرگومانهای آنها به كار می‌برد. بعنوان مثال با استفاده ازfuncall، تابع عمومیfilter را تعریف خواهیم كرد كه می‌تواند به این صورت فراخوانی شود:
    (filter ’(1 3 -9 -5 6 -3) #’plusp) ==>(1 3 6)
    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 به این صورت می‌تواند باشد:
    (my-map #’double ’(1 2 3 4))==> (2 4 6 8)
    بارها شده كه یك تابع باید یكبار استفاده می‌شد. بنابراین اگر ما بتوانیم مستقیما تعریفی از یك تابع بعنوان آرگومان از تابع نگاشت فراهم كنیم كاملا مناسب خواهد بود برای اینكار تعریف عبارت lambda را پشتیبانی می‌كند. ما قبلا به طور غیر رسمی نماد‌سازی عبارات را در بخش II بعنوان تعریف توابع بی نام یا مستعار معرفی كردیم. در Lisp عبارات lambda با استفاده از نوع خاصی از lambda تعریف می‌شوند نوع عمومی عبارت lambda به این صورت است:

    (lambda ( parameter . . . ) body . . . )

    یك عبارت lambda امكان می‌دهد تا ما تعریف تابع را از نام تابع تشخیص دهیم عبارات lambda می‌توانند به جای نام تابع در تابع funcall استفاده شوند مانند عبارت كه تابع double ما می‌تواند باشد:
    (lambda (x) (+ x x))
    برای مثال: فراخوانی تابع my-map بالا می‌تواند با استفاده از عبارت lambda مجدداً به صورت زیر بیان شود:
    (my-map #’(lambda (x) (+ x x)) ’(1 2 3 4) ==> (2 4 6 8)
    یك عبارت lambda یك شئ تابعی بر می‌گرداند كه به نام تابع متصل نیست در تعریف
    my-map ، پارامتر fn را بعنوان متغیر نام تابع استفاده می‌كنیم. وقتی شكل lambda محاسبه شد مفسر Lisp شئ تابعی را به متغیر نام تابع متصل خواهد كرد. به این طریق یك پارامتر تابع بصورت یك نام تابع پویا استفاده می‌شود. نماد # صروری است تا به Lisp بگوید كه نه تنها یك شئ تابعی را وصل كند بلكه باید اتصالات محلی و سراسری مقادیر وابسته به شئ تابعی را نیز نگه دارد. این تنها با استفاده از عملگر quote امكان‌پذیر نخواهد بود (متأسفانه به دلیل محدودیت جا جزئیات بیشتری داده نمی‌شود).

صفحه 1 از 2 12 آخرینآخرین

برچسب برای این موضوع

مجوز های ارسال و ویرایش

  • شما نمی توانید موضوع جدید ارسال کنید
  • شما نمی توانید به پست ها پاسخ دهید
  • شما نمی توانید فایل پیوست ضمیمه کنید
  • شما نمی توانید پست های خود را ویرایش کنید
  •