I am Elixir creator. There are a few downsides comparing Elixir today with Erlang. First, there are all trade-offs related to Elixir being a new language: we have fewer resources and a smaller community. Fortunately, Elixir community is growing very active (on IRC) and it is very likely you get some support on whatever you are tackling. Also, we haven't reached 1.0 yet, which means backwards incompatible changes may happen, but we do our best to properly deprecate them first.
Regarding the language features, since Elixir provides a macro system, you can apply to Elixir some of the same complaints people would apply to Lisp and meta-programming in general: i.e. people can definitely go overboard and write code that is hard to read and maintain ("magic"). On the other hand, Erlang does not provide macros and has a set of restrictions on how your code looks like (only one module per file, module forms cannot have custom expression, etc). At the end of the day, it boils down about Elixir giving you more power, but also requiring more responsibility from you to use it wisely. Some people prefer to work with a given set of strict rules.
Finally, we also do our best to have a regular and sane syntax (it is important after all to have sane macro behaviour). However, due to optional parenthesis, there is some space for ambiguity. Assuming you have a function named `abs`, `abs + 1` is treated as `abs() + 1` but `abs +1` as `abs(+1)`. Those cases are very few though and we also warn about them in the guide. It is one of the trade-offs you pay for having a more convenient syntax most of the times, so you can write:
defmodule Foo do
def bar do
1
end
end
Instead of:
defmodule(Foo) do
def(bar()) do
1
end
end
I believe this translates well some of the observations developers tell me when migrating from Erlang to Elixir.
Erlang does not provide lisp style macros. They provide macros, but they look more like templates and are limited. For example, a couple days ago I wanted to write this macro:
-define(line(Opts), case lists:keyfind(line, 1, Opts) of
{ line, Value } -> Value;
false -> 0
end).
I can call this macro as:
?line(SomeOpts)
Basically, the compiler will replace ?line by the template defined above. You cannot manipulate the AST via such macros and they contain severe limitations. In particular, the example above just works if you use it once per function. Since variables are not hygienic, after you use ?line once, the variable Value is going to be bound and it will be considered unsafe (because it is defined in just one of the branches) and your code will fail to compile if you use it again.
In case you want to manipulate the AST, you can indeed use parse transforms. But it requires a considerable amount of work to get simple stuff done and iirc you can just use one per module.
Just minor nitpick: "lisp style macros" are not necessarily hygienic either, which is why you need (gensym). Not in Scheme, though.
"iirc you can just use one per module"
I happen to use erlando[1] often (it's fun!) and I use both do and cut transforms all the time. So no, there is no limit to how many parse transforms you can use in one module.
It's true, however, that writing them is a pain, which is why I never bothered to write one (just take a look at how the 'do' is implemented) - but I just accepted this as inevitable cost of not using s-exps as a language syntax. I'll take a look at how Elixir does it, I'd be very positively surprised if it manages to get real macros convenient in non-s-exp language :)
Regarding the language features, since Elixir provides a macro system, you can apply to Elixir some of the same complaints people would apply to Lisp and meta-programming in general: i.e. people can definitely go overboard and write code that is hard to read and maintain ("magic"). On the other hand, Erlang does not provide macros and has a set of restrictions on how your code looks like (only one module per file, module forms cannot have custom expression, etc). At the end of the day, it boils down about Elixir giving you more power, but also requiring more responsibility from you to use it wisely. Some people prefer to work with a given set of strict rules.
Finally, we also do our best to have a regular and sane syntax (it is important after all to have sane macro behaviour). However, due to optional parenthesis, there is some space for ambiguity. Assuming you have a function named `abs`, `abs + 1` is treated as `abs() + 1` but `abs +1` as `abs(+1)`. Those cases are very few though and we also warn about them in the guide. It is one of the trade-offs you pay for having a more convenient syntax most of the times, so you can write:
Instead of: I believe this translates well some of the observations developers tell me when migrating from Erlang to Elixir.