Elm is a functional programming language that compiles to JavaScript. You can build websites and web applications using it. You can reliably refactor them as the needs and features grow and/or change. It has a goal is simplicity, and it is not just for beginniners.
In short...
- Reliable refactoring
- Friendly error messages
- Enforced semantic versioning (in libraries)
- No runtime errors (in practice)
Source: Elm - The Official Guide
_Note: the Official Guide is really good. I am doing a variation of examples based on "Just Enough Scala"
To follow examples in Elm, it helps if you have an understanding of the following concepts:
- values & variables
- functions
- anonymous functions
- List API
- tuples & records
We can explore Elm interactively through elm-repl
or Ellie.
We refer to elm-repl
as a REPL (a "Read-Evaluate-Print-Loop"). It's a handy, quick why to try out code.
> elm repl
---- Elm 0.19.0 ----------------------------------------------------------------
Read <https://elm-lang.org/0.19.0/repl> to learn more: exit, help, imports, etc.
--------------------------------------------------------------------------------
> x = 7
7 : number
>
> x = 7
7 : number
> y = 8
8 : number
> x + y
15 : number
> z = "hello"
"hello" : String
> z ++ ", and welcome!"
"hello, and welcome!" : String
> square s = s * s
<function> : number -> number
or, we can continue onto the next line with a slash \
> square s = \
| s * s
<function> : number -> number
There are no parentheses when executing a function:
> square 3
9 : number
Whitespace is used to delimit the argments.
We can still use parentheses to group an operation prior to it being passed as an argumnet:
> square (2 + 2)
16 : number
It's worth mentioning that even if you know about the Type Annotations used in Elm, the elm repl
is not going to handle them:
> square : Int -> Int \
| square s = \
| s * s
I cannot handle type annotations.
> \r -> r + 7
<function> : number -> number
> \r -> r + r
<function> : number -> number
> \name -> "Hello, " ++ name ++ "!"
<function> : String -> String
The List
module defines a common API that you will see in other abstract data types. You might be familiar with the operations found in the List
module from other collections APIs (like: map
, filter
, foldl
, foldr
, etc). For a more thorough listing of functions, see List
> lst = [1, 2, 3]
[1,2,3] : List number
> List.map (\i -> Debug.log "item" i ) lst
item: 3
item: 2
item: 1
[1,2,3] : List number
> square s = s * s
<function> : number -> number
> List.map square lst
[1,4,9] : List number
> List.map (\i -> i + 2) lst
[3,4,5] : List number
> List.filter (\i -> (modBy 2 i) == 1) lst
[1,3] : List Int
> List.foldr (\i j -> i + j) 0 lst
6 : number
> List.foldr (+) 0 lst
6 : number
> lst
[1,2,3] : List number
Tuples & Records
> pt = (0.1, 1.3)
(0.1,1.3) : ( Float, Float )
> Tuple.first pt
0.1 : Float
> Tuple.second pt
1.3 : Float
> zcoord = (0.2, 1.3, 0.4)
(0.2,1.3,0.4) : ( Float, Float, Float )
-- a `type alias` defined a record called Point
> type alias Point = { x : Float, y : Float }
-- when you defint `Point`, you get a constructor function that takes `Float -> Float -> Point`
> List.map (\(x, y) -> Point x y) points
[{ x = 0.1, y = 1.3 },{ x = 1.1, y = 2.2 },{ x = 0.1, y = 1.2 }]
: List Point
Given how good the "core language" overview is on "Elm Guide", I'm not sure what I'd add to it, overall.