繁体   English   中英

灵丹妙药中的语言构造与宏

[英]Language constructs vs Macros in elixir

我正在从https://elixirschool.com/en/lessons/basics/control-structures/学习控制结构,我注意到它提到了

如果您以前遇到过if / 2,并且如果您使用过Ruby,那么您很可能会熟悉,除非/ 2。 在Elixir中,它们的工作方式大致相同,但它们被定义为宏,而不是语言构造。 您可以在内核模块中找到它们的实现。

那么Elixir中的语言构造和宏之间有什么区别,何时需要编写宏?

宏是一种对编程语言进行编程的方法。 简而言之,宏是一种生成程序代码的方法,而不是始终自己编写代码。

另一方面,语言构造(有时称为“特殊形式”)是长生不老药本身的核心。 过于简单的做法可能是, if的实现不是在Elixir中完成,而是在实现Elixir的语言中完成。

假设您要使用提及的, unless

编辑: unless 提供药剂。 但是让我们假设其余的不是。

在Elixir中, unless有该语言的版本, unless没有其他内容。 Jose Valim没有实现它。 但是,您始终可以编写具有相同语义的内容:否定的if

我们希望有这一点,但我们不这样做

unless sun_shines() do 
  open_umbrella()
end

但是我们只有一个if和一个not ,所以我们可以这样写:

if not sun_shines() do 
  open_umbrella()
end

其次,宏是一种特殊的函数,但是其参数是代码,执行宏的结果也是代码。 假设我们有unless宏,它接受一个条件(即sun_shines()和主体(即open_umbrella()并返回if not sun_shines(), do: open_umbrella() 因此,宏是在“死代码”级别工作并生成“死代码”的函数。

您可能会认为这太愚蠢,无法为其编写宏。 确实如此。 但是这些类型的问题比您想象的要经常发生,因此宏是解决该问题的好方法。 这只是编程您的编程语言的一种方法。

的一个例子实施unless宏已经提供由阿列克谢Matiushkin:

defmodule MyMacros do
  defmacro unless(ast, do: block) do
    quote do
      if not unquote(ast) do
        unquote(block)
      end
    end
  end
end

在这里,您可以清楚地看到给它一个AST(抽象语法树),它将把它转换为另一个AST( quote ),并将其注入到您调用宏的位置。 请注意,这都是在编译时发生的。 您的程序目前尚未执行!

例如,假设您具有上述模块,这是您的程序:

defmodule MyProgram do 
  def my_function(x) do 
    unless sun_shining() do 
      open_umbrella()
    end
  end
end

编译之后,执行之前,您的程序将如下所示:

defmodule MyProgram do 
  def my_function(x) do 
    if not sun_shining() do 
      open_umbrella()
    end
  end
end

这个阶段称为宏扩展阶段。

另外,您可以在此处找到分别在Elixir和ExUnit中使用的两个实际宏。

https://github.com/elixir-lang/elixir/blob/d48b16cf549eca0629449a47cc5574a7170706c3/lib/ex_unit/lib/ex_unit/assertions.ex#L104

https://github.com/elixir-lang/elixir/blob/13ced80fcda1bea69037aacd4b052a0c44b4be61/lib/elixir/lib/stream/reducers.ex#L58

注意:我一直在为该答案添加越来越多的信息。 答案实际上是一整本书, 克里斯·麦考德Chris McCord )撰写的Metaprogramming Elixir是最好的一本书。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM