【发布时间】:2016-09-05 06:14:25
【问题描述】:
免责声明:我知道可以以更简单的方式编写代码,但您应该明白我将简化的代码发布到 SO。
我有一个模块Simple,它使用Included:
defmodule Simple do
use Included,
events: [
[
name: :start,
callback: fn(x) -> x * 2 end
], [
name: :finish,,
callback: fn(x) -> x * 3 ; x end
]
]
end
我希望Included 模块定义一个函数,该函数为上面列表中的每个项目获取一个参数并返回一个值。所以,我正在这样做:
defmodule Included do
defmacro __using__(opts)
events = Keyword.get(opts, :events)
quote bind_quoted: [events: events] do
events
|> Enum.each(fn(event) ->
def unquote(event[:name])(x) do
x
|> unquote(event[:callback]).()
|> IO.puts
end)
end
end
end
这里的问题是我收到了invalid quoted expression: #Function<0.105634730。我试图以另一种方式实现它:
defmodule Included do
defmacro __using__(opts)
events = Keyword.get(opts, :events)
events
|> Enum.each(fn(event) ->
quote bind_quoted: [event: event] do
def unquote(event[:name])(x) do
x
|> event[:callback].()
|> IO.puts
end
end
end)
end
end
但在这种情况下,我还没有看到定义的函数。 (没有错误,这里没有函数Simple.start/1和Simple.finish/1)。
我的问题是:
- 如何定义所需的功能?
- 为什么没有在第二种方法中定义函数?
【问题讨论】:
-
一种有效的解决方法是在
quote之前转义所有事件的:callback键:events = for event <- opts[:events] do; Keyword.update!(event, :callback, &Macro.escape/1); end。 -
@Dogbert 不幸的是我得到了
cannot escape #Function<2.45959719/1 in Included.MACRO>. The supported values are: lists, tuples, maps, atoms, numbers, bitstrings, pids and remote functions in the format &Mod.fun/arity我试图在 iex 中实现类似的东西,结果相同 =(