
Learning Elixir: My side-project - adrip
http://adrian-philipp.com/post/learning-elixir-first-side-project
======
bglusman
This looks awesome! It's also a kind of perfect companion piece to an
Elixir/Phoenix project a friend of mine, Travis, did over at Stride[1].

I also have my own social-good oriented learning-phoenix/ecto project[2],
OpenPantry, which I started some months ago after I'd learned Elixir pretty
well and done a little Phoenix micro-service, but still hadn't done anything
full stack or involving Ecto or Channels... We're actively looking for help
building out the feature set and it's for a great cause if anyone's
interested, helping those with food-insecurity to get food more easily and
with more choice than many pantry programs are currently able to provide!

[1][https://github.com/stride-nyc/remote_retro](https://github.com/stride-
nyc/remote_retro)
[2][https://github.com/MasbiaSoupKitchenNetwork/open_pantry](https://github.com/MasbiaSoupKitchenNetwork/open_pantry)

------
tmat
I think what I learned the most about my past year of working heavily in
Elixir is this.. Don't learn elixir.. learn Erlang/OTP if you really want to
harness the power of Elixir. Elixir is nothing but a series of macros which
give erlang some convenience and better syntax.

If you learn to harness the power of Erlang, while writing it in Elixir, then
you will see the beauty of it. Get away from Phoenix as fast as possible.
Seriously it will do you wonders. It's so unnecessary and cumbersome.

OTP, OTP, OTP.. can't say it enough.

~~~
jmcgough
I learned Phoenix and OTP at basically the same time. I knew I'd need to build
out a worker queueing system as part of a web app, so I started reading an OTP
book while I was building the initial structure of the Phoenix app. By the
time I needed to do more interesting things than just a crud app, I could work
with GenServers and Supervision trees.

The moment that the lightbulb went on for me was when I ran `iex -S mix` in my
Phoenix project and fired up erlang's observer to see its processes. I
realized that phoenix is just a supervision tree made up of different
microservices, much more complicated than the toy projects I'd built, but
still relied on the same OTP tools and patterns. And once you understand that,
it becomes trivial to use OTP to expand the functionality that Phoenix gives
you out of the box.

I think what you're trying to say (and I agree if you are) is that Phoenix and
Elixir are great, but you are missing out on what makes Elixir so powerful
(Erlang/OTP and BEAM) if you stop there.

~~~
tmat
Yep, that's exactly it. I'm just not very eloquent ;)

------
jamesroseman
I had a brief stint of working with Elixir a while ago, and got side-tracked
and spent that time going down the GraphQL/Relay rabbit hole instead. During
that time I was ramping up to help out on the GraphQL Elixir project [1]. I
don't know its current state, but it might be worth looking into vs Absinthe
(which I'm pretty sure was branched off that project originally).

EDIT: Looks like the repo is pretty abandoned actually, scratch that!

[1] [https://github.com/graphql-elixir/graphql](https://github.com/graphql-
elixir/graphql)

~~~
micmus
Absinthe is completely separate from that project. I think the whole community
effort is around Absinthe at the moment and it's shaping into a great library.
There's also a PragProg book coming out in Autumn "Craft GraphQL APIs in
Elixir with Absinthe" [1].

[1]: [https://pragprog.com/book/wwgraphql/craft-graphql-apis-in-
el...](https://pragprog.com/book/wwgraphql/craft-graphql-apis-in-elixir-with-
absinthe)

~~~
jamesroseman
It's not completely separate. The maintainer of Absinthe got started working
with the maintainer of GraphQL-Elixir. I'm not purporting they still work
together, just that they have common roots.

Though that's cool a book is coming out! I remember when these projects were
just getting started.

------
blindwatchmaker
Picking up new languages is fun.

I have to say things like this tickle my funny bone though:

> def backlog(board_id) when is_integer(board_id) do

What happened to good old fashioned function foo (int bar) :)

Is there an equivalent to typescript for elixir?

~~~
chickenfries
I've been reading about Erlang recently, and guards (the when clause) seem
much more expressive than something like type annotations for function
parameters. For example, TypeScript's annotations can't express something like
this (which also shows Erlang's pattern matching):

    
    
      right_age(X) when X >= 16, X =< 104 ->
        true;
      right_age(_) ->
        false.
    

[http://learnyousomeerlang.com/syntax-in-functions#guards-
gua...](http://learnyousomeerlang.com/syntax-in-functions#guards-guards)

~~~
always_good
Unless you're telling me Elixir has static analysis that can tell me that
`right_age(18) == true` then I'm not sure how that competes with types much
less is so different from any other runtime conditional.

~~~
rdtsc
> Unless you're telling me Elixir has static analysis

Sure does:
[http://erlang.org/doc/apps/dialyzer/dialyzer_chapter.html](http://erlang.org/doc/apps/dialyzer/dialyzer_chapter.html)

> I'm not sure how that competes with types much less is so different from any
> other runtime conditional.

You can write:

    
    
      f(5) ->
         "got a 5";
      f(X) when is_integer(X), X > 1000 ->
         "got an integer greater than 1000";
      f(X) ->
          "not 5 and not an integer greater than 1000".
    

Sure you can do it with an if statement in some languages. Except in Erlang
can also have the same guards on process message receive expressions. There
would have to process all messages then check the type and somehow re-insert
it back into the message queue.

~~~
always_good
Looking at the dialyzer docs and how you truncated my full question, I'm still
not sure if Elixir has static analysis that is aware of those guards or not.

~~~
rdtsc
Sorry for being confusing. I think this might be better description of static
type analysis:

[http://learnyousomeerlang.com/dialyzer](http://learnyousomeerlang.com/dialyzer)

Erlang is a dynamic, strongly typed language. Dynamic means the compiler
doesn't do static type checks. "Strongly typed" means once a variable has a
type it usually doesn't get automatically coerced to other types. So adding a
string "5" and an integer 1 doesn't return a string "6" or integer 6 but
throws an exception.

In addition to the compiler there is also a tool called Dialyzer. It's based
on the idea of Success Types (paper on it:
[http://www.it.uu.se/research/group/hipe/papers/succ_types.pd...](http://www.it.uu.se/research/group/hipe/papers/succ_types.pdf)).

It checks for type inconsistencies, violations, etc just like a compiler in a
traditional statically typed language. But it doesn't emit optimized code
based on it. So say it deduced that a variable can only be an integer between
1 and 10 it doesn't have a way to emit some optimized assembly code based on
that information. Besides the types it automatically infers, additional typing
constraints can be specified by the user.

So for the guard in question, if say the second clause of right_age(_) ->
wasn't there and it saw calls to the function with X=105, then Dialyzer would
come back with an error with something like:

    
    
       your_module:105: Clause guard cannot succeed.

------
eggy
I picked up Elixir and LFE (Lisp Flavoured Erlang) at the same time. I prefer
Lisps, and so I stuck with LFE, so my knowledge of the current state and
capabilities of Elixir is lacking. Robert Virding who co-created Erlang,
created LFE. He responded to Jose Valim in 2013 in a LFE vs Elixir thread [1].

I was accused of spreading misinformation when I made the same point recently
on HN in another Elixir thread [2].

So my question is: Does Robert Virding's point still hold about Elixir's
macros only able to use its predefined syntax, and not create new syntax like
a Lisp can. I like Elixir, I just prefer Lisp's syntax. However, if Elixir is
making these type of improvements I may want to revisit it, and to ensure I am
not repeating old, incorrect information.

Robert Virding uses this example (look at the thread for context):

>> (defmacro kl >> ((list* k v rest) `(cons (tuple ',k ,v) (kl ,@rest))) >>
(() ()))

>> which I can use

>> (kl a (+ 2 7) b 6) ==> (#(a 9) #(b 6))

Can Elixir do this or not?

Thanks!

    
    
      [1]  https://groups.google.com/forum/#!topic/lisp-flavoured-erlang/ensAkzcEDQQ
      [2]  https://news.ycombinator.com/item?id=14390916

~~~
CoderPuppy
Yes, sorta.

The point I think he was trying to make was that Lisp's syntax is less
restrictive, but that seemed to get confused by:

\- mentioning the some people say it has no syntax (which it definitely does
have)

\- saying macros can create new syntax (which they can't in Lisp)

Elixir macros are approximately the same as Lisp macros (apart from not being
able to take a variable number of arguments).

This is a straight port of that macro into Elixir:

    
    
      defp kl_i([k, v | t]) do
        quote do
          [
            {unquote(Macro.escape(k)), unquote v}
            | unquote kl_i t
          ]
        end
      end
      defp kl_i([]), do: quote do: []
      defmacro kl(l), do: kl_i l
      
      # usage
      IO.inspect kl [a, 2 + 7, b, 6]
      # => [{{:a, [line: 16], nil}, 9}, {{:b, [line: 16], nil}, 6}]
    

Note: Elixir's syntax does get in the way a bit here, the `a` and `b` are
converted into nullary calls, you could use a different escaping function to
fix this

    
    
      defp escape_key({v1, v2}), do: {escape_key(v1), escape_key(v2)}
      defp escape_key({:{}, pos, els}) when is_list(pos), do: {:{}, pos, Enum.map(els, &escape_key/1)}
      defp escape_key(els) when is_list(els), do: Enum.map(els, &escape_key/1)
      defp escape_key({sym, pos, nil}) when is_list(pos), do: Macro.escape sym

~~~
eggy
I sort of get it. But this part he writes in the discussion seems to hold, no?

"What I mean here is that elixir has a predefined syntax. It has a number of
predefined syntactic constructs, operators and function calls. And while I can
with macros change the meaning of the constructs I cannot add new constructs
or operators as the handling of macros is done after parsing. So if I want to
add something completely new it ends up syntactically being a function call.
Now elixir has many ways of disguising function calls at the end of the day
they are syntactically still function calls. For example parentheses around
arguments are optional, there is special syntax for property lists where the
keys are all atoms, special syntax for using these property lists as function
arguments, special handling of do ... end when it is a function argument, etc.
Elixir's uniform abstract syntax makes it easier to work with these but I am
still limited by only having the existing syntax."

------
ponyous
I've been learning elixir for past 10 months and will be releasing a project
to the public hopefully by the end of the month. Is anyone interested in any
specific topics? I plan to write an accompanying blog post when I release.

Stack: Elixir, RethinkDB, Inferno (react alternative) + Redux (The goal when I
started was to learn new things, hence the unusual stack)

~~~
captainbeardo
First time I've ever seen that stack. +1

------
richjdsmith
Elixir was my Koolaid when it comes to functional programming. After getting
the hang of pattern matching, I was hooked. Everything I'd do on Ruby/Rails, I
just do on Elixir/Phoenix instead.

~~~
dmix
Clojure was my FP Koolaid, but Erlang (which I learned before Elixir) really
blew my mind with it's pattern matching heavy syntax. I'm happy Elixir kept it
as part it's core design patterns. So agreed it's a great abstraction that
every modern language should be using.

That plus extensive use of list comprehensions when working with arrays.

------
jesses
Thanks for the write-up. Have you thought about using gigalixir.com instead of
Heroku?

~~~
gxespino
Sounds cool. Should probably add disclaimer that you're the founder.

~~~
jesses
Oh my bad, I usually do that. I can't seem to edit my comment though..

