DEV Community

Milan Pevec
Milan Pevec

Posted on

Elixir, Weird Syntax, Is It Really ?

Intro

So, Ive decided. To learn. Elixir. Ive started with watching some Youtube videos (Elixir Conference), just to get into it, to become attracted to it, cause time is a big constraint in my life, unfortunately, and without real attraction, there is no motivation.

Syntax

For me coming from Java, Javascript world, doing some Ruby flirting, the syntax seemed strange. A bit. I was reading official docs (Getting Started), diagonally, but I wanted to jump directly into the sea with writting one example using Ecto library. And there I saw the subject of this blog - I saw the following lines of the code:

import Config

config :app1, Friends.Repo,
  database: "app1_repo",
  username: "user",
  password: "pass",
  hostname: "localhost"

Huh? That was my first reaction. Where is function, where are parentheses, brackets ? Weird syntax, is it really ?

Drill down sir

Seing that syntax was confusing. First I tough that I will skip "why?" and just use this. "Its just like this" approach. But after a day or two I've returned to this lines again.
Ive created my own example, slowly moving towards realisation that syntax is actually great and not weird at all!

Step 1

I've created two elixir source files "canvas.exs":

defmodule Canvas do
    def draw(title, color \\ "Red by default", shape \\ "Circle by default" ) do
        IO.puts("Draw a #{shape} with the color #{color}. Title is: #{title}.")
    end
end

and "main.exs":

Canvas.draw("Nice Canvas")

I've compiled canvas.exs and run main.exs with the expected output:

Draw a Circle by default with the color Red by default. Title is: Nice Canvas.

So far so good. As you can see, we created a module, function with default parameters and we print the final string.
Now you might ask yourself, what has this to do with our subject of this blog ? You will see, we will get there.

Step 2

What if we use the keyword list data structure for parameters of our function ? Lets try.

Our main.exs is gonna change to:

options = [{:color, "Green"}, {:shape, "Square"}]
Canvas.draw("Nice Canvas", options)

As you can see, keyword list is a key-value list, where keys are atoms. Neat.

Our canvas.exs is gonna change then to:

defmodule Canvas do
    def draw(title, options \\ []) do
        color = Keyword.get(options, :color, "Red by default")
        shape = Keyword.get(options, :shape, "Circle by default")
        IO.puts("Draw a #{shape} with the color #{color}. Title is: #{title}.")
    end
end

Elixir is offering Keyword module for manipulating keyword lists. Again very neat. But so far, very javascript-ish.

Step 3

From now on, we will change only main.exs to bring it closer to our objective; Canvas module is going to stay the same.

Lets first change our keyword list. Because keys are atoms, we can use special syntax, where we use key values as following:

options = [color: "Green", shape: "Square"]

And now lets put it directly to our function call:

Canvas.draw("Nice Canvas", [color: "Green", shape: "Square"])

What if I tell you that there is more! Elixir official docs says the following:
In general, when the keyword list is the last argument of a function, the square brackets are optional.
That means we can do this:

Canvas.draw("Nice Canvas", color: "Green", shape: "Square")

Whaaat, thats so cool.

Step 4

And now the final changes. As you probably know, there are two things more:

  • for named functions parentheses are optional;
  • if we use Import we don't need to prefix functions with module name;

So our final code change is:

import Canvas

draw "Nice Canvas", color: "Green", shape: "Square"

or if we break lines:

import Canvas

draw "Nice Canvas",
  color: "Green",
  shape: "Square"

Which is (almost) exactly the same as our initial Ecto code:

import Config

config :app1, Friends.Repo,
  database: "app1_repo",
  username: "user",
  password: "pass",
  hostname: "localhost"

So now we can understand that above code is actually a call of the named function "config/3" ie. with three parameters:

  • atom :app1
  • alias Friends.Repo (which behind the scenes is an atom)
  • keyword list used as last parameter, ie. function options

Final toughts

So, is it weird ? No, I think is great, it's readable and has clarity. I like it.

Top comments (0)