如何将匿名函数传递给 Elixir 中的管道
Posted
技术标签:
【中文标题】如何将匿名函数传递给 Elixir 中的管道【英文标题】:How to pass an anonymous function to the pipe in Elixir 【发布时间】:2014-08-26 22:54:00 【问题描述】:我想这样写代码:
def boundary do
:crypto.rand_bytes(8)
|> Base.encode16
|> &("--------FormDataBoundary" <> &1)
end
但它不起作用。
【问题讨论】:
【参考方案1】:它看起来有点奇怪,但必须有效:
def boundary do
:crypto.rand_bytes(8)
|> Base.encode16
|> (&("--------FormDataBoundary" <> &1)).()
end
【讨论】:
它有什么理由这么奇怪吗?当我将函数传递给管道时,我将其视为变量(是的,我来自 javascript),但执行 (fn).() 看起来我正在立即调用它,但我不是。(&("--------FormDataBoundary" <> &1)).()
看起来您定义了一个接受 1 个参数的匿名函数,然后用零参数调用它,然后它就成为了管道的一部分?我不明白你为什么最后需要.()
。这不是调用匿名函数吗?我不想自己称呼它,我希望它成为管道的一部分。
我想我现在明白了。该函数是管道的一部分这一事实意味着管道提供第一个参数。剩下的就是调用函数了,你可以使用.()
。
一开始我很纠结。然后我意识到当你使用管道时,管道中的每个函数都是函数调用,而不是函数引用。如果您的管道中的函数具有 2+ 元数,这一点很明显,从那时起您 必须 也可以为命名函数使用括号。一旦您意识到所有命名函数也被显式调用,使用括号为匿名函数进行函数调用并不奇怪。如果它们的元数为 1,则可以省略括号(使其看起来像函数引用而不是函数调用,但它仍然是函数调用。)【参考方案2】:
相关:如果“匿名”函数已分配给变量,您可以像这样通过管道传递给它:
def boundary do
add_marker = fn (s) ->
"--------FormDataBoundary" <> s
end
:crypto.rand_bytes(8)
|> Base.encode16
|> add_marker.()
end
【讨论】:
【参考方案3】:接受的答案有效,但您可以使用
更优雅地做到这一点(&"--------FormDataBoundary#&1").()
而不是
(&("--------FormDataBoundary" <> &1)).()
这是完整的功能:
def boundary do
:crypto.strong_rand_bytes(8)
|> Base.encode16()
|> (&"--------FormDataBoundary#&1").()
end
奖励:我还用:crypto.strong_rand_bytes/1
替换了:crypto.rand_bytes/1
(elixir 1.6+ 中不存在)。
【讨论】:
【参考方案4】:你也可以这样使用:
def boundary do
:crypto.rand_bytes(8)
|> Base.encode16
|> (fn chars -> "--------FormDataBoundary" <> chars end).()
end
与其他形式相比,这种形式的一个优势是您可以轻松编写简单的“案例”语句:
def do_some_stuff do
something
|> a_named_function()
|> (
fn
:ok, something -> something
:error, something_else ->
Logger.error "Error"
# ...
end
).()
end
发件人:
Anonymous functions in pipe chain · Elixir Recipes使用fn
比couchemar's answer 更清晰一点:
def boundary do
:crypto.rand_bytes(8)
|> Base.encode16
|> (&("--------FormDataBoundary" <> &1)).()
end
...但是,对于您的特定示例,使用&
的上述表单可能是最好的。如果管道表达式更复杂,命名匿名函数参数可能更有用。
我的回答也比Nathan Long's answer简洁一点:
def boundary do
add_marker = fn (s) ->
"--------FormDataBoundary" <> s
end
:crypto.rand_bytes(8)
|> Base.encode16
|> add_marker.()
end
...如果由于某种原因您需要在管道中多次调用该函数,他的回答会更好。
【讨论】:
也可以跳过括号:|> fn x -> x end.()
【参考方案5】:
你真的不能走吗?
thing
|> func_one()
|> fn input -> do_stuff_here() end)
你可以做一些事情,比如把东西直接放到箱子里
thing
|> func_one()
|> case do
所以,我认为您可以直接输入匿名函数。
【讨论】:
最后一行需要像|> (fn input -> do_stuff_here() end).()
,否则你是正确的。
我不知道有人可以通过管道进入case
tho - 这很方便!以上是关于如何将匿名函数传递给 Elixir 中的管道的主要内容,如果未能解决你的问题,请参考以下文章
当使用局部变量将匿名函数传递给命名函数时,Javascript中的范围问题
node-java 是不是允许将匿名函数作为参数传递给 java?
在具有 GPU 加速的 arrayfun 中使用匿名函数 (Matlab)