[英]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中使用的两个实际宏。
注意:我一直在为该答案添加越来越多的信息。 答案实际上是一整本书, 克里斯·麦考德 ( Chris McCord )撰写的Metaprogramming Elixir是最好的一本书。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.