我需要根据用户的配置动态生成函数子句。为了清楚起见,想象一下我有一个原子列表:
GetCursorPos
来自,@atoms ~w|foo bar baz|a
。我需要的是生成这个功能(MCVE过于简单,但它给我的实际需要的印象):
config.exs
我目前正在做的是:
@checker fn
{:foo, _} -> false
{:bar, _} -> false
{:baz, _} -> false
_ -> true
end
它工作得很好,但我希望我过于复杂,丢失了一些简单的东西。所以,我的问题是:
有一种简单的方法可以在编译时生成函数子句吗?
答案 0 :(得分:2)
我使用3215
:
quote
输出:
defmodule A do
@atoms ~w|foo bar baz|a
@clauses Enum.flat_map(@atoms, fn tag ->
quote do: ({unquote(tag), _} -> false)
end) ++ quote(do: (_ -> true))
defmacro checker, do: {:fn, [], @clauses}
end
defmodule B do
require A
f = A.checker
IO.inspect f.({:foo, :ok})
IO.inspect f.({:bar, :ok})
IO.inspect f.({:baz, :ok})
IO.inspect f.({:quux, :ok})
end
我希望false
false
false
true
能够正常工作,但现在这是一个解析错误,所以我们必须执行quote(do: a -> b)
,它将我们想要的引用片段包装在列表中。
我还希望quote(do: (a -> b))
在unquote
内部fn
内部工作,但事实并非如此。
quote
我相信这两个都是错误或缺少功能。