我遇到了一些Erlang代码,我试图将其转换为Elixir,以帮助我学习这两种语言并理解其中的差异.宏观和元编程一般是我仍然试图解决的话题,所以希望你能理解我的困惑.
Erlang代码
-define(p2(MAT, REP),
p2(W = MAT ++ STM) -> m_rep(0, W, STM, REP))
% where m_rep is a function already defined.
Run Code Online (Sandbox Code Playgroud)
对我来说,似乎在上面的代码中,有两个单独的p2宏定义映射到一个名为的私有函数m_rep.但是在Elixir中,似乎只能有一个模式匹配定义.Elixir也有可能有不同的吗?
这些不是两个定义.第一行是宏,第二行是替换.令人困惑的是,宏与它生成子句的函数同名.例如,当像这样使用宏时:
?p2("a", "b");
?p2("c", "d").
Run Code Online (Sandbox Code Playgroud)
以上内容将扩展至:
p2(w = "a" ++ stm) -> m_rep(0, w, stm, "b");
p2(w = "c" ++ stm) -> m_rep(0, w, stm, "d").
Run Code Online (Sandbox Code Playgroud)
您可以使用erlc -P生成的.P文件向您显示宏扩展对代码的影响.看看这个稍微简单,可编辑的例子:
-module(macro).
-export([foo/1]).
-define(foo(X),
foo(X) -> X).
?foo("bar");
?foo("baz");
?foo("qux").
Run Code Online (Sandbox Code Playgroud)
使用erlc -P macro.erl您将获得以下输出macro.P:
-file("macro.erl", 1).
-module(macro).
-export([foo/1]).
foo("bar") ->
"bar";
foo("baz") ->
"baz";
foo("qux") ->
"qux".
Run Code Online (Sandbox Code Playgroud)
在Elixir中,您也可以使用宏定义多个函数子句.它更冗长,但我认为它也更清晰.Elixir等价物将是:
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
Run Code Online (Sandbox Code Playgroud)
您可以使用它来定义多个函数子句,就像erlang对应的一样:
defmodule MyModule do
require MyMacros
MyMacros.p2('a', 'b')
MyMacros.p2('c', 'd')
end
Run Code Online (Sandbox Code Playgroud)