[英]Elixir macros, quoting and unquoting
我正在學習Elixir,並嘗試使用Macro系統。
我正在嘗試使變量可用於將由宏與其他代碼包裝在一起的塊,但是我顯然做錯了什么。
這是我的起點宏,可以正常工作。 我知道在Elixir中有更多慣用的方法可以迭代,因此我將其寫為練習:
defmodule Loops do
defmacro times(n, [do: block]) do
quote do
Enum.each(1..unquote(n), fn(_) -> unquote(block) end)
end
end
end
import Loops
times 3 do
IO.puts "Hello!"
end
現在,我要完成的工作就是能夠從do
塊中引用計數器。 因此,如果我給fn
參數起一個合適的名字:
Enum.each(1..unquote(n), fn(_) -> unquote(block) end)
# becomes:
Enum.each(1..unquote(n), fn(counter) -> unquote(block) end)
我希望能夠做這樣的事情:
times 3 do
IO.puts "Hello! iteration n: #{counter}"
end
但是,由於undefined function counter/0
因此無法正常工作並引發CompileError
。 我傳遞給宏調用的do
塊引發了錯誤,我發現這有點違反直覺,因為我認為在調用unquote()
時,該塊將被放置在擴展代碼中。
我是用錯誤的方式解決問題,還是根本不可能?
您可以使用Kernel.var!/2
來使counter
成為“不衛生的”變量。 這將確保生成的代碼可用它,而不會被Elixir的宏系統重命名。
defmodule Loops do
defmacro times(n, [do: block]) do
quote do
Enum.each(1..unquote(n), fn(var!(counter)) ->
unquote(block)
end)
end
end
end
defmodule Main do
require Loops
def main do
Loops.times 3 do
IO.puts "Hello! iteration n: #{counter}"
end
end
end
Main.main
輸出:
Hello! iteration n: 1
Hello! iteration n: 2
Hello! iteration n: 3
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.