簡體   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