$ irb
[1, 2, 3, 4].
select {|n| n % 2 == 0}.
map {|n| n * n}.
reduce {|sum, n| sum + n}
# 20
vs $ iex
[1, 2, 3, 4] \
|> Enum.filter(fn(n) -> rem(n, 2) == 0 end) \
|> Enum.map(fn(n) -> n * n end) \
|> Enum.reduce(0, fn(n, sum) -> sum + n end)
That Ruby code is so compact that I split it on multiple lines only to make the comparison easier.Even Python is more compact even if it's harder to read because of the reverse order (I'm sure that there is a nested comprehension for that but it's beyond my comprehension skills) from functools import reduce
reduce(lambda x, sum: sum + x, \
map(lambda x: x * x, \
filter(lambda x: x % 2 == 0, \
[1, 2, 3, 4])))
# 20
The problem here is having to type Module.function(value) vs object.methodOO languages have a more compact notation because objects act as namespaces. Elixir has alias but it doesn't help much and must be used wisely. alias Enum, as: E would only confuse people and gain little. Then Elixir has too many do end compared to Ruby (coming from Ruby I feel them unnecessary), but that's not a big deal. Moving from syntax to programming patterns, having to define twice my functions in GenServer (internal API and public API) is too much boilerplate. I'd like to have time to study macros really well and end up with a DryGenServer that lets me def the external API with the internal implementation. Maybe I'll defmacro a defasync and a defsync, that generate the standard "double" GenServer functions. |
I've discovered that it's significantly easier for me to get in the flow state of mind while programming in Elixir. Comfortable and powerful. Definitely a worthwhile investment of time and effort.