我遇到了一些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.
对我来说,似乎在上面的代码中,有两个单独的p2
宏定义映射到名为m_rep
的私有函数。但是在Elixir中,似乎只能有一个模式匹配定义。是否有可能在Elixir中有不同的?
答案 0 :(得分:8)
这些不是两个定义。第一行是宏,第二行是替换。令人困惑的是,宏与它生成子句的函数同名。例如,当像这样使用宏时:
?p2("a", "b");
?p2("c", "d").
以上内容将扩展为:
p2(w = "a" ++ stm) -> m_rep(0, w, stm, "b");
p2(w = "c" ++ stm) -> m_rep(0, w, stm, "d").
您可以使用erlc -P
生成.P
文件,该文件将向您展示宏扩展对代码的影响。看看这个稍微简单,可编辑的例子:
-module(macro).
-export([foo/1]).
-define(foo(X),
foo(X) -> X).
?foo("bar");
?foo("baz");
?foo("qux").
使用erlc -P macro.erl
,您将获得macro.P
的以下输出:
-file("macro.erl", 1).
-module(macro).
-export([foo/1]).
foo("bar") ->
"bar";
foo("baz") ->
"baz";
foo("qux") ->
"qux".
在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
可以用来定义多个函数子句,就像erlang对应的那样:
defmodule MyModule do
require MyMacros
MyMacros.p2('a', 'b')
MyMacros.p2('c', 'd')
end
答案 1 :(得分:3)
我无法在这里帮助自己。 :-)如果您使用的是LFE (Lisp Flavoured Erlang)之后的宏,那么使用更多的宏处理比erlang或elixir更好。它也兼容两者。
答案 2 :(得分:2)
-define(p2(MAT, REP),
p2(w = MAT ++ stm) -> m_rep(0, w, stm, REP))
% where m_rep is a function already defined.
上面的代码有很多问题。
在Erlang中没有带有多个子句的宏。上面的代码没有定义映射到名为p2
的私有函数的m_rep
宏的两个单独定义。它的作用是定义一个2参数宏,它定义一个p2
函数,它接受一些参数并调用m_rep
。但是,内部p2
函数的参数定义不正确:
++
,第二个参数不是列表W
,一个变量,而不是一个小的w
,一个原子?)您是否尝试测试相等性(==
而不是=
),而不是进行作业?如果是这样,你必须使用警卫。
此外,在我看来,您尝试使用w
和stm
,好像它们是变量并将它们传递给m_rep
,但它们并非如此! Erlang中的变量必须以大写字母开头。另一方面,Elixir中的变量则没有。你可能会混淆两种相似但仍然不同的语言的概念。
我的一般建议是选择一种语言并对其进行良好的学习,并且只有在您掌握了这些知识后才能尝试不同的语言。如果您对编程完全陌生,请选择Erlang - 它更简单,预先学习的东西较少。如果您已经了解Ruby,请选择Elixir,或者更多地了解您的技能。
请详细说明您的意图,我或许可以提出表达它的代码。上面的片段太模糊了。