通过宏创建匿名函数 [英] Creating anonymous functions via macros

查看:77
本文介绍了通过宏创建匿名函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想制作一个由宏组成匿名函数的API,例如

I'm tying to make an API where an anonymous function are composed from macros, e.g.

transform [x, y], do: x + y
transform x,      do: x

应使用 transform head body [:do] 作为头匿名功能的主体。例如,上面的宏调用上面的示例应该被收集到:

should use the transform head and body[:do] as the heads and bodies for an anonymous function. For example, the above macro calls The example above should be collected into:

fn [x, y] -> x + y; x -> x end

使用unquote片段,很容易创建新的命名函数 def s,但没有新的匿名函数:

With unquote fragments it's easy to create new named function defs, but not new anonymous functions:

iex> val = 1
iex> fn() -> unquote(val) end
** (CompileError) iex:99: unquote called outside quote
(elixir) src/elixir_exp_clauses.erl:23: :elixir_exp_clauses.clause/5
(elixir) src/elixir_fn.erl:33: anonymous fn/3 in :elixir_fn.expand/3
(stdlib) lists.erl:1237: :lists.map/2
(elixir) src/elixir_fn.erl:36: :elixir_fn.expand/3

这是我当前的进度:

defmacro anonymous_fn(parts) do
  quote bind_quoted: [parts: parts] do
    fn_branches = for {head, body} <- parts, do: {:->, [], [[head], body]}
    unquote({:fn, [], fn_branches})
  end
end

但是,嵌套的unquote会失败,而相同的 unquote称为外部引用错误。

However, the nested unquote fails with the same unquote called outside quote error.

在这一点上,我将仅使用一个简单的匿名函数,宏方法有些过头,但我仍然想知道

At this point I'm just going to use a plain anonymous function, the macro approach was overkill, but I'd still be interested to know if this is possible.

谢谢!

解决方案


至此,我将仅使用一个简单的匿名函数,该宏方法有些过头,但我仍然想知道是否

At this point I'm just going to use a plain anonymous function, the macro approach was overkill, but I'd still be interested to know if this is possible.

这正是我要提出的。 :)匿名函数要简单得多,它还可以使作用域规则清晰明了,可以很好地与组合等配合使用。

This is exactly what I was going to propose. :) The anonymous function is much simpler and it also makes the scoping rules clear, works nice with composition and so on.

取消引用片段确实是定义模块函数的便捷方法,则它们并不会完全申请任何代码,因为这样就无法知道何时取消引用片段适用。例如,如果您有以下内容:

unquote fragments are really a convenience for defining module functions, they do not apply for any code exactly because it then becomes impossible to know when the unquote fragment applies. For example, if you had this:

def foo do
  fn -> unquote(bar) end
end

您怎么知道它是否适用于 foo 还是匿名函数?无论如何,要回答您的问题,您需要在引号中明确定义代码:

How do you know if it is meant to apply to foo or to the anonymous function? In any case, to answer your question, you need to define the code explicitly in the quote:

defmacro anonymous_fn(parts) do
  fn_branches = for {head, body} <- parts, do: {:->, [], [[head], body]}
  {:fn, [], fn_branches}
end

或:

defmacro anonymous_fn(parts) do
  fn_branches = for {head, body} <- parts do
    quote do: (unquote(head) -> unquote(body))
  end
  {:fn, [], fn_branches}
end

这篇关于通过宏创建匿名函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆