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

الم (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 در مثالی که در اپلیکیشن تک صفحه ای آن‌ها وجود دارد، مطرح شده‌است که تقریباً تمامی قطعات مشابه در آپدیت، ویو، اشتراکات، تجزیه مسیر و توابع ساختاری تکرار می‌شوند.

کد نمونه 
-- 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 که می‌تواند به جاوا اسکریپت نیز تبدیل شود

منابع 

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