Few words of introduction

We all love Elixir. It’s expressive, it’s extremely readable and - first and foremost - It runs on BEAM — an incredible virtual machine that turns concurrency into something as natural and expected as NullPointerExceptions in Java 7.

But as every language does, it also has its flaws. Some are inherent, some are just religious choices that had to be made one way or another; and as the user (or rather fan) base grows, so does the demand to express your own preferences. Changes like piping to the last argument instead of the first can be introduced with simple macros. Some people craving for more advanced ideologies create entire toolsets extending the language (like Railway Oriented Programming or Saša Jurić’s Exactor). Some others commit to entire frameworks that start to look like DSLs instead (Witchcraft).But even smartest macro can’t solve everything without surpassing the biggest meta-programmer’s limitation: syntax. So that’s what we changed.

Arguably one of the loudest religion choices is typing. Private jokes like “Strong typing is for weak minds” and “If you shoot yourself in the foot, it’s easier to solve the problem by being careful not to aim the gun at your foot than it is to make guns that don’t point down” roam around the community. Whether types are hot or not, is out of this article’s scope. I like strong types. And I like Elixir. And that’s why Elchemy was made.

What does strong typing give us anyway?

Generally strong typing pays attention so you don’t have to. You put a typo in function params? Compiler will tellYour arguments are in wrong order. Compiler will tellYou wrongly treat a list of {:ok, value} tuples as if they were just value’s. Compiler will tell.

So whether your application works on complex nested structures, you like extra safety, or you just suffer from short attention span, static typing probably will serve you well.

Classically we’ll write a sum as a recursion, where we take a head of a list and add it to the application of the same function on the tail , with an exception of returning just 0 if the list is empty.Which should look like this

Save our file and…. wait a second. There’s an error.

Oh… That’s right! Since we’re no longer in a world of dynamic typing, we can’t just add any two things together. Addition is an operator reserved for numbers only.That means our type signature is incorrect.Let’s fix it by changing to sum : List Int -> Int

Perfect!Let’s run our test case again and see how it’s doing

Alright! We’ve got our first functional program. Now let’s add some bells and whistles to it. We’ll start by removing the test we just wrote. We don’t need an entire test case just for a simple sum function. Let’s make it a doctest!

Remove the test case and write a beautiful doc for our newly born function.Same as in Elm we write a docstring using {-| -} comment block. So let’s do exactly that

That should be just right. Let’s run our mix test again.

If we removed our previous test case, we should now have 7 tests 0 failures report from our test suite; each one of our doctest lines being a separate test case.

But what did we write anyway?

Although the Elchemy code is sufficient on it’s own and there is no need to look at the generated output, it’s good to make a sanity check, so we know what does the written code do to the rest of our codebase.

To do that, we can look at generated Main.ex file inside our output lib/ folder.

This is the part relevant to what we just wrote.

Let’s break it down.

At #23 We start with a @doc string that works as a documentation for our function. Then between #26–36 we have three generated examples in Elixir doctest format.At Line #41 We can see the typespec signature for a curried version of our function — this is how our function will be called from inside Elchemy.Line #42 Is a regular typespec, generated only for function usage out of Elchemy — directly from Elixir codeLine #43 is a bit of Elchemy magic that makes our function accessible in curried formLine#44–49 is exactly what we’d do writing the function by hand, with a tiny exception of a mysterious dot in sum.(rest) which for now will remain unexplained. Generally it’s because in Elchemy everything is curried.

That’s all for part one.In the next part we’ll learn how to create an entire library, using modules from elchemy-core, defining your own types, type aliases and operators.