是否可以使用宏初始化列表,然后使用另一个宏根据该列表在2个不同的模块中生成2组函数?
伪代码示例:
defmodule ABC do
defmacro rules() do
quote do
defrule("a")
|> defrule("b")
|> defrule("c")
end
end
end
defmodule BasicTokenizer do
use TokenizerBuilder
require ABC
ABC.rules()
|> deftokenizer()
end
defmodule ExtendedTokenizer do
use TokenizerBuilder
require ABC
ABC.rules()
|> defrule("d")
|> deftokenizer()
end
import ExUnit.Assertions, only: [assert: 1, assert: 2]
assert BasicTokenizer.tokenize("a") == "a"
assert BasicTokenizer.tokenize("b") == "b"
assert BasicTokenizer.tokenize("c") == "c"
assert ExtendedTokenizer.tokenize("a") == "a"
assert ExtendedTokenizer.tokenize("b") == "b"
assert ExtendedTokenizer.tokenize("c") == "c"
assert ExtendedTokenizer.tokenize("d") == "d"
我尝试了以下方法,但我陷入deftokenizer
:
defmodule TokenizerBuilder do
defmacro __using__(_) do
quote do
require unquote(__MODULE__)
import unquote(__MODULE__)
end
end
defmacro defrule(str) do
quote do
[unquote(str)]
end
end
defmacro defrule(rules, str) do
quote do
Enum.concat(unquote(rules), [unquote(str)])
end
end
defmacro deftokenizer(rules) do
# rules is AST, how to get builded list value outside quote?
Enum.each(rules, fn(str) ->
quote do
def tokenize(unquote(str)) do
unquote(str)
end
end
end)
end
end
答案 0 :(得分:1)
很难准确说出你要求的内容,但请考虑以下代码:
iex(1)> f = &String.upcase/1
&String.upcase/1
iex(2)> g = &String.trim/1
&String.trim/1
iex(3)> h = &String.reverse/1
&String.reverse/1
iex(4)> fs = [f,g,h]
[&String.upcase/1, &String.trim/1, &String.reverse/1]
iex(5)> r = for f <- fs, do: f.("hello")
["HELLO", "hello", "olleh"]
我的意思是如果您正在尝试构建要应用于值的函数列表,那么这可能会起作用。我认为有一些方法可以构建一个应用于值的函数列表,而不必使用宏来执行此操作。但是你的用例对我来说还不是很清楚。