Erlang vs Elixir Macros

plo*_*lot 10 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.
Run Code Online (Sandbox Code Playgroud)

对我来说,似乎在上面的代码中,有两个单独的p2宏定义映射到一个名为的私有函数m_rep.但是在Elixir中,似乎只能有一个模式匹配定义.Elixir也有可能有不同的吗?

Pat*_*ity 8

这些不是两个定义.第一行是宏,第二行是替换.令人困惑的是,宏与它生成子句的函数同名.例如,当像这样使用宏时:

?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)

  • 你在这里教过我很多东西.谢谢你这么详细的答复. (2认同)