I have came across some Erlang code which I am trying to convert to Elixir to help me learn both of the languages and understand the differences. Macros and metaprogramming in general is a topic I am still trying to get my head around, so hopefully you will understand my confusion.
The Erlang code
-define(p2(MAT, REP),
p2(W = MAT ++ STM) -> m_rep(0, W, STM, REP))
% where m_rep is a function already defined.
To me, it seems that in the above code, there is two separate definitions of the p2
macro that map to a private function called m_rep
. In Elixir though, it seems that it is only possible to have one pattern matching definition. Is it possible to have different ones in Elixir too?
In terms of concurrency support, Elixir is preferred by the developers over Erlang. In terms of ease of application, fault-tolerant mechanism and distributed applications, Elixir is preferred mostly in the current environment.
Yes! Elixir is slightly slower because we dispatch to Enum. reduce and Erlang doesn't perform a remote call.
So write macros responsibly. Elixir already provides mechanisms to write your everyday code in a simple and readable fashion by using its data structures and functions. Macros should only be used as a last resort. Remember that explicit is better than implicit.
A macro is defined as follows: -define(Const, Replacement). -define(Func(Var1,...,VarN), Replacement). A macro definition can be placed anywhere among the attributes and function declarations of a module, but the definition must come before any usage of the macro.
Elixir offers more flexibility than Erlang. You can assign the same variable more than once in Elixir, however, Erlang doesn’t allow that. The focus on reducing programming errors: Elixir reduces the number of programming errors by its very design.
Elixir runs on the Erlang Virtual Machine, and it’s a general-purpose programming language. This open-source language emphasizes on functional programming, concurrency, and fault tolerance. This dynamically-typed language features several similarities with Erlang.
You can get several advantages if you use Erlang, and these are as follows: Ease-of-use: Erlang values simplicity. This language uses the functional programming paradigm, which encourages simplicity. Erlang goes further since its syntax allows simpler programming.
Most developers coding in Elixir use Phoenix, a powerful framework that uses several features of Ruby on Rails. The other popular open-source frameworks for this language are as follows: Joe Armstrong, Robert Virding, and Mike Williams created Erlang as a proprietary software of Ericsson.
These are not two definitions. The first line is the macro, the second line is the replacement. The confusing bit is that the macro has the same name as the function for which it is generating clauses. For example when using your macro like this:
?p2("a", "b");
?p2("c", "d").
the above will be expanded to:
p2(w = "a" ++ stm) -> m_rep(0, w, stm, "b");
p2(w = "c" ++ stm) -> m_rep(0, w, stm, "d").
You can use erlc -P
to produce a .P
file that will show you the effects of macro expansion on your code. Check out this slightly simpler, compilable example:
-module(macro).
-export([foo/1]).
-define(foo(X),
foo(X) -> X).
?foo("bar");
?foo("baz");
?foo("qux").
Using erlc -P macro.erl
you will get the following output to macro.P
:
-file("macro.erl", 1).
-module(macro).
-export([foo/1]).
foo("bar") ->
"bar";
foo("baz") ->
"baz";
foo("qux") ->
"qux".
In Elixir you can define multiple function clauses using macros as well. It is more verbose, but I think it is also much clearer. The Elixir equivalent would be:
defmodule MyMacros do
defmacro p2(mat, rep) do
quote do
def p2(w = unquote(mat) ++ stm) do
m_rep(0, w, stm, unquote(rep))
end
end
end
end
which you can use to define multiple function clauses, just like the erlang counterpart:
defmodule MyModule do
require MyMacros
MyMacros.p2('a', 'b')
MyMacros.p2('c', 'd')
end
I can't help myself here. :-) If it's the macros you are after then using LFE (Lisp Flavoured Erlang) gives you much better macro handling than either erlang or elixir. It also is compatible with both.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With