[英]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.