Elixir 中的命名函数和匿名函数有啥区别?

Posted

技术标签:

【中文标题】Elixir 中的命名函数和匿名函数有啥区别?【英文标题】:What Is The Difference Between A Named And An Anonymous Function In Elixir?Elixir 中的命名函数和匿名函数有什么区别? 【发布时间】:2017-04-04 05:42:57 【问题描述】:

命名函数和匿名函数有什么区别?

hello = &("Hello, #&1") 是如何成为匿名函数的?

【问题讨论】:

【参考方案1】:

函数本身没有名称,它绑定到一个变量,但你可以将它内联放置在任何需要函数的地方,例如:

Enum.map([1,2,3],  &("Hello, #&1") )

没有名字。匿名的。

【讨论】:

【参考方案2】:

主要区别之一是范围。你可以在函数体中访问什么。

Elixir 中的命名函数被分组到模块中,它们的范围仅限于给它们的参数。

匿名函数可以在任何地方定义,并且可以访问其周围可见的任何内容。行话是它们是“闭包”,即它们“关闭”周围的范围。

我们来看一个例子:

c = 10

anon = fn(a, b) -> a + b + c end
anon.(1, 2) # => 13, because c is available in the anonymous function

# The module below will fail to compile, because c isn't available
defmodule MyModule do
  def named(a, b), do: a + b + c
end

您可以使用 & capture operator 从命名函数创建匿名函数,并且它可以访问您当前的作用域。这很常见,因为许多函数都期望其他函数作为参数。浏览the docs for Enum,你会看到很多例子。

你会注意到我这样调用匿名anon 函数:anon.(1, 2),而不是anon(1, 2)。它使两种函数之间的区别在您的代码中更加明确。

José 对related question 给出了很好的回答。

【讨论】:

这可能会导致更多的混乱而不是帮助,但我发现整个“命名”函数与匿名函数的事情具有误导性。实际上只有闭包和表达式。模块是在编译时定义复杂表达式的方法,闭包是在运行时定义复杂表达式的方法。 这个解释对我来说是最有意义的,并且对我来说确实巩固了两者之间的区别。但是,我不太明白的一部分是您对已被捕获到匿名函数中的命名函数“将如何访问您当前的范围”的评论。你是说被捕获到匿名函数中的命名函数仍然可以访问它被定义的范围(即在它被定义的模块内)?【参考方案3】:

命名函数需要在模块中定义。匿名函数没有这个限制。

在您的示例中,&("Hello, #&1") 是匿名函数部分。它使用捕获操作符 &,所以这个函数只是写fn (x) -> "Hello, #x" end的更短的方式。 &1 是函数参数的占位符。您可以将该匿名函数分配给一个变量(在这种情况下为hello)。要通过变量访问函数,请使用 hello.("Derek")别忘了点!

请记住,Function 也是 Elixir 中的一种类型,并且函数是一等公民,这就是为什么您可以将其分配给变量并使函数返回其他函数的原因。

【讨论】:

以上是关于Elixir 中的命名函数和匿名函数有啥区别?的主要内容,如果未能解决你的问题,请参考以下文章

如何将匿名函数传递给 Elixir 中的管道

命名和未命名匿名 Javascript 函数之间的区别

在 JavaScript 中使用匿名函数有啥缺点吗?例如。内存使用?

我可以在这个 Elixir 匿名函数中避免元组参数吗?

内置函数及匿名函数

内置函数随笔及匿名函数