General aspects between Elm and JS

This is Part 1 in a series about Elm for JavaScript Developers. I've been programming in JavaScript for a while, and hearing people speak so highly about Elm inspired me to give it a try! Studying Elm has raised several questions about this language. The idea of this text is to introduce Elm to JavaScript developers like myself.

If you're reading this, you're probably aware of what Elm is, but let's go overt it. Elm is a functional language that compiles to JavaScript. It is a young language, created in 2012 by Evan Czaplicki as his thesis.

In this blog series, we will compare Elm with JavaScript. Today, we will analyse some of their unique features and illustrate the differences between them.

Let's do a Hello World in Elm to get started!

mkdir hello_world
cd hello_world
vim HelloWorld.elm

We will create a basic Elm module that outputs Hello, World!

import Html exposing (text)

main =
  text "Hello, World!"

We want to generate an HTML text node, so we import the Html module and expose its text function.

We can use elm-reactor: an interactive development tool that makes it easy to develop and run Elm applications:

elm-reactor

Now that the reactor is running, we can visit http://localhost:8000 in our browser and see the result: Hello World on the screen!

Elm has an elm_package.json file which is similar to the package.json file that node uses. Here is ours:

{
  "version": "1.0.0",
  "summary": "helpful summary of your project, less than 80 characters",
  "repository": "https://github.com/user/project.git",
  "license": "BSD3",
  "source-directories": [
    "."
  ],
  "exposed-modules": [],
  "dependencies": {
    "elm-lang/core": "5.1.1 <= v < 6.0.0",
    "elm-lang/html": "2.0.0 <= v < 3.0.0"
  },
  "elm-version":
    "0.18.0 <= v < 0.19.0"
}

elm creates an elm-stuff folder to store its dependencies and build artifacts in. This is similar to the node_modules directory in JavaScript.

Now that we have created our Hello World App, let's look at the differences between both languages.

Syntax

For a JavaScript developer, the first thing that comes to mind when you see Elm code is the syntax. You’re probably thinking Elm syntax is really weird, because it looks nothing like JavaScript.

The Elm site has a quick Syntax Guide to help you understand the syntax.

Let's look at some differences:

Functions

Elm functions rely on whitespace rather than commas and curly brackets. The return is implicit. There is no return keyword.

sum a b =
  a + b

In this sum function, you can see: - There is no return keyword - It doesn't use commas to separate the parameters - There is an equal sign after the params

Variables and Types

Elm is strongly typed, but it has type inference. This means you don't need to say that a variable is a number or a string - if you use it like one, Elm can figure it out.

In Elm we can create union types which means the type can have one of the described values.

type Animal = Elephant | Horse | Cow

In our case, Animal can be an Elephant or Horse or Cow.

In Elm we can also use Type Annotation. This is an optional feature, although highly recommended. You can see it below:

sum: Int -> Int -> Int
sum a b =
  a + b

A type annotation should be written right above the function definition. In our case we have sum: Int -> Int -> Int as a type annotation. It means our function receives two Int and it returns Int.

DOM

Later we will have an episode just to talk about how Elm manages the DOM. For the moment, just keep in mind Elm uses a Virtual DOM system, like React. Elm does not mutate the DOM directly as vanilla JavaScript might.

If you use vanilla JavaScript or even jQuery you can directly mutate DOM elements without using a representation of it.

To represent the DOM, Elm uses plain old vanilla functions. If you have used React, this would be similar to JSX.

If you want to get a better idea of how fast Elm renders HTML, check out this blog post from Evan.

Compiled vs Interpreted

Elm is a compiled language. JavaScript is an interpreted language.

In Elm if you have a function that receives two numbers and you pass two strings, it won't even compile. Elm has a static type system. All the types are discovered at compilation time.

Let's use the sum function above. We're going to pass two characters rather than numbers. Let's try to compile that:

Detected errors in 1 module.


-- TYPE MISMATCH ---------------------------------------------------------------

The 1st argument to function `sum` is causing a mismatch.

9|                 sum '3' '2')
                       ^^^
Function `sum` is expecting the 1st argument to be:

    number

But it is:

    Char

Yay! The Elm Compiler <3

Here we can see the Elm compiler saying TYPE MISMATCH. It expected a number but we passed a Char.

Let's try this in JavaScript. We're going to pass two numbers first and then we will pass two strings.

function sum(a,b){
  return a + b
}

console.log(sum(3,2))
// => 5
console.log(sum('3','2'))
// => '32'

For the first call, by passing only numbers, we got the correct result, as we expected it. With the second call, by passing two strings, we got: 32! JavaScript has concatenated our two strings.

The Elm compiler is really good at telling us what we should do or what we meant to do. It's really good to have someone helping us like the Elm compiler.

Having static type checking means we don't have to have those errors at execution time. We can completely avoid them in compilation time.

Type correctness does not guarantee program correctness. Just because we have our Elm compiler “helper” doesn’t mean you don't need to test your code. A compiled and static typing language doesn’t magically produce a great app.

Show me the code

We will create a simple Elm app that checks if a number is odd or even. We will have a button to increment this number and once we increment or decrement the number, the view will update and say ODD or EVEN.

Let's do it.

module Main exposing (..)

import Html exposing (beginnerProgram, div, button, text)
import Html.Events exposing (onClick)


type Msg
    = Increment
    | Decrement


main =
    beginnerProgram { model = model, view = view, update = update }


model =
    { quantity = 0 }


update msg model =
    case msg of
        Increment ->
            { model | quantity = model.quantity + 1 }

        Decrement ->
            { model | quantity = model.quantity - 1 }


checkNumber n =
    if ((rem n 2 == 0) == True) then
        "EVEN"
    else
        "ODD"


view model =
    div []
        [ button [ onClick Decrement ] [ text "-" ]
        , div [] [ text (toString model) ]
        , div [] [ text (checkNumber model.quantity) ]
        , button [ onClick Increment ] [ text "+" ]
        ]

You can check this code on Ellie. Ellie is a pretty good Elm live editor.

In this example, we are using Html.beginnerProgram, you can check out more about it in the Elm documentation. checkNumber is the function that checks if a number is odd or even, and returns a string, saying ODD or EVEN.

Once you increment the number, it calls the checkNumber function and the result will be on the screen.

This is Part 1 on Elm for JavaScript developers.

Interesting Elm Videos

Resources