Elm

Elm היא שפת תכנות, שמותאמת ספציפית ליצירת ממשקי משתמש גרפיים (GUI) לדפדפני אינטרנט באופן דקלרטיבי. היא נוצרה בשנת 2012 על ידי אוון קזאפליקי (Evan Czaplicki), בתור עבודת התזה שלו. Elm היא שפת תכנות פונקציונלית, ופותחה תוך מתן דגש על שימושיות, ביצועים, ויכולות להתמודד עם שגיאות (robustness, ). בעמוד הבית של השפה, מובטח שלא תהיינה שגיאות בזמן ריצה, תודות לבדיקת הטיפוסים של המהדר של Elm.

היסטוריה 
Elm תוכננה בהתחלה בשנת 2012 על ידי אוון קזאפליקי בתור התזה שלו. הגרסה הראשונה של Elm הגיעה עם דוגמאות קוד רבות ועורך קוד מקוון. אוון הצטרף ל-Prezi בשנת 2013 על מנת לעבוד שם בפיתוח Elm, ובשנת 2016 עבר ל-NoRedInk כמפתח קוד פתוח. באותה השנה גם הקים את הארגון "Elm Software Foundation".

המימוש הראשוני של המהדר של Elm התמקד ב-HTML, CSS ו-Javascript. סט הכלים של השפה הורחב, ונוספו REPL (כתיבת קוד בקונסולה באמצעות הרצה של שורה אחר שורה, או בשמה המלא: Read Eval Print Loop), מנהל חבילות, דיבאגר (מנפה שגיאות) שניתן להריצו גם לאחור, ומתקינים לשפה אשר זמינים למערכות ההפעלה macOS ו-Windows. בנוסף, ל-Elm יש ספריות קוד אשר נוצרו על ידי הקהילה , וכן עורך קוד מקוון מתקדם - Ellie, שניתן לשמור בו עבודה ולייבא ספריות קוד שיצרה הקהילה.

ארכיטקטורת Elm 
ארכיטקטורת Elm היא דפוס ליצירת אפליקציות web אינטראקטיביות. אפליקציות ב-Elm בנויות כך באופן טבעי, אך סוגים אחרים של פרויקטים יכולים להשתמש בשיטה זו, בשל יעילותה. תוכנה ב-Elm מחולקת ל-3 חלקים: Model, View ו-Update (בקיצור : MVU). ה-Model אחראי על מצב האפליקציה, ה-View אחראי על החזרת המודל לתוך קובץ ה-HTML (דף האינטרנט), וה-Update מעדכן את ה-Model באמצעות שליחת הודעות אליו. קונספט זה מזכיר את תבנית Model-View-Controller (או בקיצור, MVC), אשר פופולרית בתכנות אפליקציות עם ממשקי משתמש גרפיים (GUI).

בארכיטקטורת Elm, שליחת הודעות ל-Update היא הדרך היחידה לשנות את מצב האפליקציה. באפליקציות מורכבות יותר, הודעות ל-Update יכולות להגיע ממקורות שונים: אינטראקציה עם המשתמש, אתחול המודל, תגובה לאירועים (events) חיצוניים כגון שינוי גודל החלון ושעון המערכת, וכדומה.

מגבלות השפה 
Elm לא תומכת ביצירת מחלקות, ולפיכך לא תומכת בעיקרון הפולימורפיזם המתבטא ביצירתן, כגון יצירת פונקציות אשר פועלות על מספר מחלקות המקיימות ממשק או יורשת ממחלקת אב מסוימת, או פעולות גנריות אשר יכולות לקבל כל סוג נתונים. לדוגמה, ב-Elm אין פעולת map גנרית, אשר מקבלת מבנה נתונים ופעולה, ומבצעת את הפעולה על כל אחד מהאיברים. במקום, ישנן פעולות ספציפיות לכל סוג נתונים, אשר רצות משם המודול של סוג הנתונים. לדוגמה, על מנת להריץ את פעולת ה-map ב-List וב-Set נקרא לפעולות List.map ו-Set.map בהתאמה. לעומת זאת, בשפות פונקציונליות אחרות כגון Haskell או PureScript, ישנה פעולת Set אחת לכל סוגי הנתונים. בשל כך, קיבל קזאפליקי (מפתח השפה) בקשות ליצירת פיצ'ר שכזה ב-Elm משנת 2015 והלאה (ייתכן שמוקדם יותר). בנוסף לכך, כפי שהוצג על ידי כותב הספר "Elm In Action", בפרויקטים גדולים נדרשת חזרה על מקטעי קוד דומים ואף זהים, וכך המתכנת נדרש לכתוב קוד רב, עבור עבודה יחסית מועטה. מקטעי קוד אלו נקראים boilerplate code .

דוגמאות קוד 
-- This is a single line comment

{- This is a multi-line comment.
 It can span multiple lines.
-}

{- It is possible to {- nest -} multi-line comments -}

-- 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)

-- 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 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 entirely new types 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 value left right ->
 1 + max (depth left) (depth right)

ראו גם 
 Ocaml
 F#
 Haskell

קישורים חיצוניים

הערות שוליים

שפות תכנות פונקציונליות
תוכנות שהושקו ב-2012