Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

The biggest practical downside with Elixir relative to Crystal is lack of types. The per-thread GC is an important advantage, though.


With pattern matching [1] and guards [2] you often don't miss explicit types.

[1] http://elixir-lang.org/getting-started/pattern-matching.html

[2] http://elixir-lang.org/getting-started/case-cond-and-if.html...


Elixir has optional typing though. You can type check with Erlang's Dialyzer.


Dialyzer uses success types, which don't always let you know when you have a soundness problem. The only thing you can count on is that if it does cry out, there certainly is something you need to fix. It also lacks parametric polymorphism, which means you often lose a great deal of useful type information. The theory behind Dialyzer is impressive, but I was pretty disappointed with it in practice.


You didn't enable the right flags.


What flags?


Try using Wunderspecs, Woverspecs, and Wspecdiffs. You'll find that dialyzer catches things that are more the shape of what you'd accept a more typical type-checking system to catch.


Oh great, thanks! Unfortunate that I missed it. Still no luck on the parametric polymorphism though... :(


That's what Type Variables are explicitly for. They present the necessary semantics for bounded parametric polymorphism. In fact that's really the only reason they exist at all. The rest of the sub-type system works without them, but parametric polymorphism wouldn't work without them.

I don't know if the Erlang/Dialyzer docs cover that specifically, but I know the originial paper on Dialyzer and Dialyzer type specs does.


I know you can do stuff like:

    @type pair(t, u) :: {t, u}
    @type result(t, e) :: {:ok, t} | {:error, e}
I'm more talking about type parameters on functions, and also constraining by behaviors and protocols. For example the typespec for Elixir's Stream.map/2 (http://elixir-lang.org/docs/stable/elixir/Stream.html#map/2):

    @spec map(Enumerable.t, (element -> any)) :: Enumerable.t
Note all the other similarly unspecific type definitions. In a parametrically polmorphic lang, you could do something like:

    @spec map[e1: Enumerable, e2: Enumerable](e1.t, (e1.element -> e2.element)) :: e2.t
And perhaps even intersections of behaviours and protocols:

    @spec foo[a: Eq & Ord](a.t, a.t) :: bool
('scuse the Elixir syntax...)




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: