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

الم (Elm) نوعی زبان برنامه نویسی خاص دامنه می‌باشد و برای ایجاد واسط‌های نگاره ای کاربر که بر پایه مرورگر وب هستند، استفاده می‌شود. البته باید ایجاد این واسط‌ها به‌طور اعلانی (برنامه‌نویسی اعلانی) باشد. الم کاملاً تابعی می‌باشد و با هدف کاربرد پذیری، عملکرد و توانمندی ساخته شد. شعار آن این است «عملا هیچ استثنائی حین رانش (runtime) وجود نخواهد داشت». این قابلیت با استفاده از کنترل نوع استاتیکی که کامپایلر این زبان دارد میسر شده‌است.

## تاریخچه
الم در ابتدا توسط اوان چاپلیکی (Evan Czaplicki) در سال ۲۰۱۲ به عنوان تز پایان‌نامه اش ساخته شد. اولین نسخه الم با بسیاری مثال و یک ویرایشگر آنلاین ارائه شد و نشان داد که در مرورگر وب نیز استفاده از آن راحت است. اوان در سال ۲۰۱۳ به گروه برنامه نویسی پرزی(Prezi) ملحق شد تا روی الم کار کنند و در سال ۲۰۱۶ به عنوان مهندس اوپن سورس به نو رد اینک (No Red Ink) رفت و همچنین شرکت نرم‌افزاری الم را برپا کرد.

پیاده‌سازی‌های اولیه کامپایلر الم HTML, CSS و JavaScript را هدف قرار داده بود. سری ابزارهای اصلی الم نیز گسترش پیدا کردند و حالا شامل یک REPL، سامانه مدیریت بسته، اشکال زدا یا دیباگری که قابلیت گذر در زمان را دارد و نصب کننده‌هایی که برای macOS و Windows هستند، می‌باشد. الم همچنین دارای فضایی برای کتاب‌خانه‌های ساخت عموم است و ویرایشگری به نام الی دارد. الی یک ویرایشگر آنلاین پیشرفته است که اجازه ذخیره کار و استفاده از کتاب‌خانه‌های عمومی را می‌دهد.

## ویژگی‌ها
الم یک سری ساختارهای زبانی کوچک مثل عبارات مرسوم if، عبارات let برای حالت محلی و عبارات case برای تطبیق الگو دارد. به عنوان یک زبان برنامه نویسی، الم توابع بی‌نام، توابعی به عنوان آرگمان‌ها و توابعی که می‌توانند توابع دیگر را برگردانند را نیز پشتیبانی می‌کند که در مورد آخر اغلب این کار با استفاده جزئی از توابع کری شده امکان‌پذیر است. توابع با مقدار فراخوان می‌شوند. ساختار توابع الم شامل مقادیر تغییرناپذیر، توابع سره و نوع گذاری استاتیکی به همراه type inference یا اصطلاحاً استنتاج نوعی می‌شود. برنامه‌های بر پایه الم HTML را از طریق یک DOM مجازی، رندر یا ارائه می‌کنند و ممکن است با استفاده از «جاواسکریپت به عنوان یک سرویس» با کد دیگر تعامل کنند.

### تغییرناپذیری
تمامی مقادیر در الم تغییرناپذیر هستند یعنی پس از ایجاد یک مقدار نمی‌توان آن را اصلاح کرد. الم از داده ساختار ماندگار برای پیاده‌سازی آرایه‌ها، ست‌ها و لغتنامه‌ها در کتابخانه معمولی استفاده می‌کند.

### انواع استاتیکی
الم به شکل استاتیکی نوع گذاری شده‌است. حاشیه نویسی‌های نوعی اختیاری هستند (به دلیل استنتاج نوعی) ولی به شدت کمک کننده هستند. حاشیه نویسی‌ها روی خط بالای تعریف، قرار دارند (برعکس زبان‌های خانواده C که نام‌ها و نوع‌ها از هم جدا هستند). الم از تک کالن برای ابلاغ پیام has type استفاده می‌کند.

نوع‌ها شامل اصولی چون رشته‌ها و اعداد صحیح و ساختارهای پایه داده شامل لیست‌ها، رکوردها و مجموعه‌های چندتایی هستند. توابع نوع‌هایی دارند که با جهت نوشته شده‌اند مثل `round : Float -> Int`

نوع‌های کاستوم به برنامه نویس اجازه می‌دهند تا نوع‌هایی سفارشی را برای نشان دادن داده به شکل مچ شده یا ارتباط گرفته با دامنه ایجاد کند.

نوع‌ها می‌توانند اشاره به یک سری نوع دیگر داشته باشند مثلاً `List Int.`

نوع‌ها همیشه بزرگ نوشته می‌شوند. نام‌هایی با حروف کوچک، متغیرهای نوع هستند. برای مثال یک `List a` لیستی از مقادیر با نوع نامشخص است. این، نوع لیست خالی و آرگومانی به `List.length` هست که منکر موارد لیست می‌باشد. چندین نوع خاص وجود دارد که برنامه نویس‌ها برای تعامل با زمان رانش (runtime) الم از آن‌ها استفاده می‌کنند؛ مثلاً `Html Msg` یک درخت DOM را نشان می‌دهد که گرداننده‌های رخداد آن همگی پیام‌هایی با نوع `Msg` تولید می‌کنند.

جای اینکه مستقیماً به هر مقدار اجازه میرا بودن بدهیم (مثل `undefined` از جاواسکریپت یا یک اشاره گر هیچ مقدار)، کتابخانه معمولی الم یک نوع `Maybe a` تعریف می‌کند. کدی که یک مقدار دلخواه را با استفاده از این نوع تولید یا کنترل می‌کند و به تمامی کدهای دیگر مقداری از نوع گفته شده را تضمین می‌دهد.

الم تعدادی از کلاس‌های نوعی درون ساختاری نیز دارد: `number` که شامل `Int` و `Float`  می‌باشد تا استفاده از اپراتورهای عددی را مثل (`+`) و (`*`) آسان‌تر کند، `comparable`  که شامل اعداد، کرکترها، رشته‌ها، لیست اشیاء قابل قیاس و مجموعه ای از اشیاء قابل قیاس می‌شود تا استفاده از اپراتورهای مقایسه ای را آسانتر کند و `appendable`  که شامل رشته‌ها و لیست‌هایی می‌باشد تا الحاق با (`++`) را آسانتر کند.

### مدول سیستم (برنامه‌نویسی ماژولی)
الم مدول سیستمی دارد که به کاربران اجازه می‌دهد تا کد خود را به بخش‌های کوچک‌تری تبدیل کنند که به آن‌ها مدول می‌گویند. مدول‌ها می‌توانند جزئیات پیاده‌سازی را مثل توابع کمکی و کد مرتبط به گروه را باهم مخفی کنند. مدول‌ها نقش فضای نام یا namespace را برای کد وارد شده بازی می‌کنند مثل `Bitwise.and`

کتابخانه‌های ثالث (یا پکیج‌ها) از یک مدول یا بیشتر از یک مدول تشکیل شده‌اند و از Elm Public Library قابل دسترسی هستند. با توجه به semver تمامی کتابخانه‌ها نسخه دار یا اصطلاحاً ورژن دار هستند که این کار با استفاده از کامپایلر یا دیگر ابزارها اعمال می‌شود. این بدین معناست که تغییر دادن نوع یک تابع یا حذف کردن آن تنها در یک نسخه اصلی امکان‌پذیر می‌باشد.

### قابلیت همکاری با HTML, CSS و جاوا اسکریپت
الم برای ارتباط با Javascript از انتزاعی به نام ports استفاده می‌کند. این انتزاع به مقادیر اجازه می‌دهد تا داخل و خارج از الم جریان پیدا کنند که همین باعث پیوند بین Elm و Javascript می‌شود.

الم کتابخانه ای به نام elm/html دارد که یک برنامه نویس می‌تواند در آن HTML و CSS نیز تایپ کند. این کار از روش DOM(مدل شیء گرای سند) مجازی استفاده می‌کند تا به روز رسانی‌ها را مفید واقع کند.

### پشتیبانی (backend)
الم رسماً از توسعه بخش سمت سروری پشتیبانی نمی‌کند. تیم اجرایی اصلی هدف کلی خود را این نمی‌دانست بلکه تمرکز خود را روی توسعه نهایی این برنامه گذاشته بود. از این رو چندین پروژه تکی وجود دارد، بدین منظور که امکان استفاده از الم به عنوان پشتیبان یا back-end را افزایش دهد. پروژه‌ها عموماً روی نسخه ۰٫۱۸٫۰ الم قرار دارند چرا که نسخه‌های جدید آن از کد native و چندین ویژگی دیگر پشتیبانی نمی‌کنند. دو راه برای استفاده از الم با BEAM (ماشین مجازی Erlang) وجود دارد. یکی از پروژه‌ها الم را مستقیماً روی محیط اعمال می‌کند در حالی که دیگری آن را به Elixir کامپایل می‌کند. پروژه ای دیگر نیز فکر ایجاد یک چارچوب یا فریم ورک پشتیبانی برای الم را داشت که توسط زیرساخت Node.js تغذیه می‌شد. هیچ‌یک از این پروژه‌ها به مرحله اجرایی نرسیده‌است.

## The Elm Architecture
الگوی Elm Architecture الگویی برای ساخت اپلیکیشن‌های فعال در وب می‌باشد. اپلیکیشن‌های بر پایه الم معمولاً به این شکل ساخته می‌شوند اما برای پروژه‌های دیگر این کانسپت می‌تواند کارساز باشد.

یک برنامه برپایه الم همیشه به سه بخش تقسیم می‌شود:

# مدل: وضعیت اپلیکیشن
# ویو: تابعی که مدل را به HTML تبدیل می‌کند.
# آپدیت: تابعی که مدل‌ها را با تکیه بر پیام‌ها به روز می‌کند.
این ۳ بخش هسته Elm Architecture هستند.

به‌طور مثال اپلیکیشنی را تصور کنید که یک عدد و گزینه ای را نشان می‌دهد که با فشردن آن عدد افزایش پیدا می‌کند. در این قضیه تنها چیزی که باید داشته باشیم یک عدد است پس مدل ما می‌تواند به سادگی `type alias Model` `=` `Int` باشد. تابع `view` با کتابخانه `Html` تعریف شده که عدد و گزینه را نشان می‌دهد. برای به روز کردن عدد باید پیامی را به تابع `update` ارسال کنیم که با استفاده از یک نوع سفارشی مثل `type Msg` `=` `Increase` قابل انجام است.

مقدار `Increase` آن را به گزینه ای که در تابع `view` تعریف شده بود متصل می‌کند تا زمانی که کاربر گزینه را فشار می‌دهد `Increase` به تابع `update` داده شود که بتواند با افزایش عدد مدل را به روز کند.

در Elm Architecture ارسال پیام‌ها به `update` تنها راه تغییر وضعیت می‌باشد. در اپلیکیشن‌های پیچیده‌تر پیام‌ها می‌توانند از چندین منبع وارد شوند: تعامل کاربر، قالب بندی مدل، تماس‌های داخلی از `update`، اشتراکاتی با رخدادهای اضافی (تغییر مجدد ابعاد پنجره، ساعت سیستم، تعامل با Javascript و …) و تغییرات URL و درخواست‌ها.

## محدودیت‌ها
الم، پلیمورفیسم یا چند ریختی‌های higher-kinded را که زبان‌هایی همچون Haskell و PureScript ارائه می‌دهند و ساخت کلاس‌های نوعی را پشتیبانی نمی‌کند.

این یعنی برای مثال، الم یک تابع بعدی `map` ندارد که میان چندین ساختار داده مثل `List` و `Set` حرکت کند. همچین توابعی در الم توسط نام مدولشان احضار یا خوانده می‌شوند، برای مثال خواندن `List.map` و `Set.map`

در Haskell یا PureScript فقط یک تابع `map` داریم. این یک خواسته معلوم در لیست خواسته‌های چاپلیکی از سال ۲۰۱۵ بوده‌است.

یک رویداد دیگر، زیاد بودن حجم boilerplate در پروژه‌های متوسط تا به بالا بوده‌است. این موضوع توسط نویسنده Elm in Action در مثالی که در اپلیکیشن تک صفحه ای آن‌ها وجود دارد، مطرح شده‌است که تقریباً تمامی قطعات مشابه در آپدیت، ویو، اشتراکات، تجزیه مسیر و توابع ساختاری تکرار می‌شوند.

## کد نمونه

```elm
-- This is a single line comment.

{-
This is a multi-line comment.
It is {- nestable. -}
-}

-- Here we define a value named `greeting`. The type is inferred as a `String`.
greeting =
    "Hello World!"

 -- It is best to add type annotations to top-level declarations.
hello : String
hello =
    "Hi there."

-- Functions are declared the same way, with arguments following the function name.
add x y =
    x + y

-- Again, it is best to add type annotations.
hypotenuse : Float -> Float -> Float
hypotenuse a b =
    sqrt (a^2 + b^2)

-- We can create lambda functions with the `\[arg] -> [expression]` syntax.
hello : String -> String
hello = \s -> "Hi, " ++ s

-- Function declarations may have the anonymous parameter names denoted by `_`, which are matched but not used in the body.
const : a -> b -> a
const k _ = k

-- Functions are also curried; here we've curried the multiplication
-- infix operator with a `2`
multiplyBy2 : number -> number
multiplyBy2 =
    (*) 2

-- If-expressions are used to branch on `Bool` values
absoluteValue : number -> number
absoluteValue number =
    if number < 0 then negate number else number

 -- Records are used to hold values with named fields
book : { title : String, author : String, pages : Int }
book =
    { title = "Steppenwolf"
    , author = "Hesse"
    , pages = 237
    }

-- Record access is done with `.`
title : String
title =
    book.title

-- Record access `.` can also be used as a function
author : String
author =
    .author book

-- We can create tagged unions with the `type` keyword.
-- The following value represents a binary tree.
type Tree a
= Empty
    | Node a (Tree a) (Tree a)

-- It is possible to inspect these types with case-expressions.
depth : Tree a -> Int
depth tree =
    case tree of
        Empty ->  0
        Node _ left right ->
            1 + max (depth left) (depth right)
```


## جستارهای وابسته
* PureScript: یک زبان برنامه نویسی با تایپ قوی و کاملاً کاربردی که به جاوا اسکریپت کامپایل می‌شود.
* دلیل: یک پسوند نحو و زنجیره ابزار برای OCaml که می‌تواند به جاوا اسکریپت نیز تبدیل شود

## منابع

رده:چارچوب‌های نرم‌افزاری تحت وب
رده:زبان‌های برنامه‌نویسی ایستا
رده:زبان‌های برنامه‌نویسی تطبیق الگو
رده:زبان‌های برنامه‌نویسی دامنه-مشخص
رده:زبان‌های برنامه‌نویسی ساخته‌شده در ۲۰۱۲ (میلادی)
رده:زبان‌های تابعی
رده:کامپایلرهای کد منبع به کد منبع
رده:نرم‌افزارهای ۲۰۱۲ (میلادی)
رده:نرم‌افزارهای دارای اجازه‌نامه ام‌آی‌تی