If you had to choose one single feature in Elixir that you love the most, what would it be?

With typespecs, not only you get visual clarities, but you can get more with dialyxir.

2 Likes

immutable data as much as pattern matching for me

to be blunt, I would miss pattern matching and immutable data even with José :wink:

Jośe valim
From a ruby ninja to elixir creator. What’s coming next.

I also liked pattern matching, but it came along with erlang.

2 Likes

I would say the combination of function overloading and pattern matching in the function head. As far as I know that combination is unique to erlang and elixir.

I wonder if referencing “function overloading” in context of Elixir/Erlang should best be avoided. In other languages overloaded functions are separate functions discriminated by arity and/or parameter types. In Elixir functions of the same name but different arity are separate functions - but other than that:

  • the terminology of “multi-clause function
  • the fact that the order of the clauses matters
  • and the fact that the syntax for a multi-clause anonymous function looks like this:
iex> my_function = fn
  {:ok, x} -> "Everything is ok: #{x}"
  {:error, x} -> "There was an error: #{x}"
end

all suggest that all the clauses of the same arity (and name) belong to the same function. Sure patterns and guards can mimic discrimination by parameter type - but in principle each clause is part of the same function.

So when the documentation states things like:

Specifications can be overloaded just like ordinary functions.

@spec function(integer) :: atom
@spec function(atom) :: integer


it's bound to create confusion.
3 Likes

If it’s in Elixir (regardless from where it stems or however many other languages have it) then it is eligible for this thread :003:

Off topic fork moved here.

1 Like

This is not a feature, per se, but Phoenix. And of equal value to me, is the functional paradigm of Elixir.

2 Likes

I’ve been using Elixir’s Gettext module quite a lot lately (to create multilingual sites). It really is well-done and enjoyable to use, and similar to Phoenix, seems to be built with macros. So, while I don’t code macros myself, I have to admire the resulting power and declarative constructs that it can enable in Elixir.

3 Likes

Oh yes, definitely, Plug and Phoenix and Mix are full Elixir creations, they definitely are features!! ^.^

I think this really depends on where you are coming from when you start learning elixir. Obviously, if you are coming from other languages that have this feature like haskell you probably won’t think “method overloading” when you see this.

If having pattern matching in the function head is confusing to newcomers it’s probably because when they see it they immediately think method overloading. Generally speaking, this is more of a problem when developers are learning a new language in general because they are trying to map/force their current knowledge on top of the language they are trying to learn.

Not having pattern matching in the function head means that the developer would be coming up with a new name for a function that does EXACTLY the same thing or the programmer would now have to take responsibility for the conditional check (like every other language) instead of letting the language do it.

There is also a developer ergonomic effect by pattern matching in the function head: cohesion is much easier to achieve. Given the example above, if you are performing a check on whether the first value is :ok or an :error, then you could easily make the argument that there are 2 reasons for that function to change instead of one. Pattern matching in the function head lifts the logic so the programmer is only coding that function for that specific logic branch. This makes it much easier to change code later without breaking anything else.

That being said, you could say that once the programmer learns to read the entire function head, that it would create less confusion not more since the function head communicates MORE information like when when the function can be called.

The community :slight_smile: . I think everything starts in the community; all of Elixir’s other features could be re-created from there.

I love the civilized form of discourse an collaboration that is possible with you all. I really like the way Elixir’s core team responds to feedback and encourages/stimulates people to contribute, and I also really enjoy the larger community that has formed around this. You are wonderful people. It really feels special to be able to be part of this.

Maybe it sounds cheesy, but it’s something that might not be said often enough.
I love you guys :heart:!

4 Likes

An interesting idea, ‘what if’ Elixir’s named function definitions matched the anonymous function definitions, so like:

def blah do
  :ok, x -> x * 2
  :error, _ -> :error
end

def blah do
  (:ok, x) -> x * 2
  (:error, _) -> :error
end

Or so…

Not Elixir, but OTP is the magic that makes Elixir happen. So, for me OTP!

I think that bunching all the functions clauses together in one unit is better, it pushes the idea that this is one function and shows more clearly all the bits which comprise the function. Otherwise, in the worst case, you may need to scan the whole module to find the function clauses. I know this is not encouraged but it is legal. Or has it been changed now? However writing macros becomes easier if you can split the function clauses.

And yes, I am influenced by my past with Erlang. :wink:

I entirely agree, that is why I like how OCaml does it, a ‘multi-head test’ is done via the function keyword:

let someFunc = function
| Blah x -> string_of_int x
| Vwoop 0 -> "invalid"
| Vwoop x when x<0 -> "Lower Vwoop"
| Vwoop x -> "Vwoop"
| ...

Elixir does still require function clauses to be together though, but otherwise they ‘look’ like separate function definitions. Of course macro’s and super change all that up too. ^.^

For note, super means that a function was defoverrideable theFunction... first, which means that each function internally gets a unique name, and when the module is finally compiled the ‘last’ one defined gets the real name, and the ‘super’ call inside it just delegates to the previously named one. Interesting method to work around the one-definition rule, though again I still like how OCaml does it:

let someFunc x -> x * 2

(* This references the previously defined function *)
let someFunc x -> 2 + someFunc x

(* The `rec` completely hides prior definitions, instead this references itself *)
let rec someFunc x -> if x <= 0 then 0 else someFunc (x-1)
1 Like

Who said, flattery does not pay :wink:

3 Likes

Haha! Well, a little bit of gratitude does not hurt, right? :wink:

And I’m being sincere btw. I really think this forum makes Elixir even better and easy to adopt… :slight_smile:

2 Likes

It’s the second most liked post in this thread so we can’t be doing too badly Robert :lol:

And yes, it does pay :icon_razz: the more you love the forum the more incentivised we are to get you lots of cool prizes and juicy discounts :003: …and we’ve got some awesome stuff for 2018!

(But more on that in our New Year announcement - which I’m running a bit late with sorry - New Years, my birthday, and my mum’s birthday all in one week! :101: Hopefully have it all done by next week though :023:)

2 Likes

also because I liked it too :wink:

2 Likes