میراندا (زبان برنامه‌نویسی)

خلاصه

Miranda یک زبان کند و کاملاً تابعی است. به این معنی که این زبان اثرات جانبی و خواص برنامه‌نویسی امری را ندارد. یک برنامه به زبان Miranda(که به عنوان Script شناخته می‌شود) مجموعه‌ای از معادلات می‌باشد که توابع مختلف ریاضی و انواع داده‌های جبری را تعریف می‌کند. کلمه مجموعه در اینجا مهم است: به‌طور کل ترتیب معادلات مهم نیست و برای استفاده از موجودیت‌ها الزامی در تعریف پیشاپیش آن‌ها وجود ندارد.
از آنجایی که الگوریتم تجزیه به صورت هوشمند از آرایش متن (توگذاری) استفاده می‌کند، به ندارت پیش می‌آید که استفاده از براکت لازم باشد و استفاده از پایان دهنده به دستورها نیز لازم نیست. این خصیصه که از ISWIM الگو برداری شده در occam و Haskell نیز مورد استفاده قرار گرفت و بعدها نیز توسط Python به شهرت رسید.
توضیحات در اسکریپت‌های عادی توسط کاراکتر || ارائه شد طوری‌که تا انتهای خط ادامه می‌یابد. قرارداد دیگر برای توضیحات حالتی بود که روی کل سند تحت عنوان «اسکریپت باسواد» تأثیر می‌گذاشت، به صورتی که هر خطی توضیحات در نظر گرفته می‌شد مگر اینکه با کاراکتر> شروع می‌شد.
پایه Miranda انواع char، num و bool می‌باشند. یک رشته کاراکتری به‌طور ساده لیستی از کاراکترهاست، در حالی که نوع num به‌طور داخلی بین دو فرم تبدیل می‌شود: اعداد صحیح با دقت دلخواه (به عبارت دیگر اعداد بزرگ) فرم پیش فرض، و در صورت لزوم مقادیر معمول ممیز شناور.
چندتایی‌ها همانند رکوردها در زبان‌های شبه پاسکال دنباله‌ای از عناصر مختلط بالقوه هستند، وتوسط پرانتزها نوشته می‌شوند:
this_employee = («Folland, Mary», ۱۰۵۶۰, False, ۳۵)
 week_days = ["Mon","Tue","Wed","Thur","Fri"]
در عوض لیستها رایج‌ترین ساختار داده‌ای مورد استفاده در Miranda می‌باشند. لیستها توسط کروشه‌ها نوشته می‌شوند و عناصر آن‌ها توسط کاما از هم جدا می‌شوند. عناصر لیست‌ها همگی باید از یک نوع باشند:
week_days = ["Mon","Tue","Wed","Thur","Fri"]
اتصال لیست‌ها توسط ++، تفاضل آن‌ها توسط --، ایجاد آن‌ها توسط :، اندازه آن‌ها توسط # و اندسی دهی آن‌ها توسط ! انجام می‌شود بنابراین:
days = week_days ++ ["Sat","Sun"]days = "Nil":days
 days!۰ ? "Nil"
 days = days -- ["Nil"]
 #days ? ۷
چند راه سریع برای ایجاد لیست‌ها نیز وجود دارد:.. برای لیستهایی به کار می‌رود که عناصر آن‌ها سری‌های ریاضی اند و امکان داشتن گام افزایشی غیر از یک را نیز برای آن‌ها فراهم کرده:
fac n = product [۱..n]
 odd_sum = sum [۱٬۳..۱۰۰]
رایج‌ترین و قوی‌ترین تسهیلات ایجاد لیست‌ها در Miranda توسط «list comperhension»ها ارائه می‌شود (که قبلاً تحت عنوان عبارت‌های ZF شناخته می‌شدند)، که به دو صورت عمده استفاده می‌شود:
عبارتی که به دنباله‌ای از جمله‌ها اعمال می‌شود:
squares = [ n * n | n <- [۱..] ]
که به این صورت خوانده می‌شود: لیستی از مربع‌های n که n عضوی از اعداد صحیح مثبت است.
و به صورت سری‌های بازگشتی:
powers_of_۲ = [ n | n <- ۱, ۲*n.. ]
همانطور که در این دو مثال می‌بینیم Miranda امکان داشتن لیست‌هایی با طول بی‌نهایت را می‌دهد، که ساده‌ترین مثال لیست اعداد صحیح مثبت است: [۱..].
علامتگذاری اجرای توابع به سادگی توسط کنار هم قرار دادن انجام می‌شود مثل SIN X.
در Miranda همانند اکثر زبان‌های کاملاً تابعی دیگر توابع از نوع first-class (سطح بالا) می‌باشند که این به این معنی است که توابع می‌توانند به عنوان پارامتر به توابع دیگر ارسال شوند، به عنوان نتیجه بازگردتنده شوند یا به عنوان عناصر ساختارهای داده‌ای منظور شوند، و نکته مهم دیگر این است که توابعی که دو یا بیشتر پاررمتر دارند می‌توانند «partially parameterised» (تا حدودی معیّن) بشوند یا به عبارتی با تعداد کمتری از پارامترهایشان فراخوانی شوند. این کار تابعی می‌دهد که در صورت تعیین شدن باقی پارامترها نتیجه نهایی را می‌دهد. به عنوان مثال:
add a b = a + bincrement = add ۱
این مثال تابعی به نام increment ایجاد می‌کند که مقدار یک را به آرگمانش اضافه خواهد کرد. در واقع add ۴ ۷ تابع دو پارامتری add را می‌گیرد آن را به ۴ اعمال می‌کند و یک تابع تک پارامتری می‌گیرد که آرگومانش را به ۴ خواهد افزود سپس آن را به ۷ اعمال می‌کند.
هر تابعی با دو پارامتر می‌تواند به یک عملگر میانوند تبدیل شود(برای مثال در تابع بالا، جمله $add تا حدودی به عملگر + شباهت دارد) و هر تابع میانوندی که دو پارامتر می‌گیرد می‌تونه به تابع معادلش تبدیل بشه. بنابراین:
increment = (+) ۱
راهی ساده برای ایجاد تابعی است که مقدار یک را به آرگومانش اضافه می‌کند. به‌طور مشابه در:
half = (/ ۲)reciprocal = (۱ /)
دو تابع یک پارامتری ایجاد می‌شوند، مفسر در هر دو حالت بالا می‌فهمد که کدام یک از دو پارامتر عملگر تقسیم ارسال شده‌اند. مثلاً در حالت اول تابع حاصل همواره آرگومان خود را نصف خواهد کرد.
با وجود اینکه Miranda یک زبان برنامه‌سازی با انواع قوی است (strongly-typed)، بر تعیین نوع به صورت صریح پافشاری زیادی ندارد. در صورتی که نوع یک تابع به صورت صریح مشخص نشود مفسر اون رو با توجه به پارامترهای تابع و اینکه آن‌ها در تابع به چه صورت مورد استفاده قرار گرفته‌اند استنتاج می‌کنه. علاوه بر انواع پایه (char، num، bool) این زبان یک نوع "anything" نیز دارد و برای مواقعی استفاده می‌شود که نوع پارامترها مهم نباشد، مثلاً در معکوس کردن یک لیست.
rev [] = []rev (a:x) = rev x ++ [a]
که می‌تونه به لیستی با هر نوع از عناصر اعمال بشه، در صورتی که اعلان نوع آن به صورت صریح به صورت زیر خواهد بود:
rev :: [*] -> [*]
نهایتاً این که این زبان مکانیزم‌هایی برای ایجاد و مدیریت ماژول‌های برنامه، ای را داراست که توابع داخلی آن‌ها از دید برنامه‌هایی که این ماژول‌ها را فرا می‌خوانند پوشیده‌است.