Erlang vs Elixir宏

Erlang vs Elixir宏,erlang,elixir,Erlang,Elixir,我遇到了一些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宏有两个单独的定义,它们映射

我遇到了一些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中,似乎只有一个模式匹配定义是可能的。在长生不老药中也可能有不同的定义吗?

这不是两个定义。第一行是宏,第二行是替换。令人困惑的是,宏与为其生成子句的函数具有相同的名称。例如,使用宏时,如下所示:

?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中,还可以使用宏定义多个函数子句。它更详细,但我认为它也更清楚。长生不老药的等效物是:

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
上面的代码有很多问题

Erlang中没有包含多个子句的宏。上面的代码没有定义映射到名为
m_rep
的私有函数的
p2
宏的两个单独定义。它所做的是定义一个双参数宏,它定义了一个
p2
函数,该函数接受一些参数并调用
m_rep
。但是,内部
p2
函数的参数定义不正确:

  • 它尝试在第二个参数不是列表的情况下使用
    ++
  • 它试图给一个原子赋值(你是说一个大写的
    W
    ,一个变量,而不是一个小的
    W
    ,一个原子?)
  • 它在不允许赋值的地方尝试赋值-在函数头中
你有没有试着测试平等性(
=
而不是
=
),不做作业?如果是这样,你必须使用一个防护装置

此外,在我看来,您试图使用
w
stm
,就好像它们是变量并将它们传递给
m_rep
,但它们不是!Erlang中的变量必须以大写字母开头。另一方面,长生不老药中的变量则不然。这可能是因为你混淆了两种相似但仍然不同的语言的概念

我的一般建议是选择一种语言并学好它,然后在掌握了这些知识之后再尝试另一种语言。如果您对编程完全陌生,请选择Erlang——它更简单,需要提前学习的东西更少。若你们已经了解Ruby或者你们的技能更适合立即销售,那个么选择长生不老药


请说更多关于您的意图,我可能会想出代码来表达它。上面的代码片段太模糊了。

我在这里忍不住想说::-)如果是您所使用的宏,那么使用它可以提供比erlang或elixir更好的宏处理。它也与两者兼容。

我不知道您是否熟悉C和Lisp,但一个简单的类比是Erlang的宏类似于C宏(即简单的编译时字符串替换),Elixir的宏类似于Lisp宏(即可以操作AST的代码)。@Onriocatenacci这非常有趣!非常感谢您帮助我理解。:-)关于变量名,您是正确的。抱歉造成混乱!你在这里教了我很多。谢谢你这么详细的回答。
-define(p2(MAT, REP), 
        p2(w = MAT ++ stm) -> m_rep(0, w, stm, REP))

% where m_rep is a function already defined.