我正在学习Elixir,想知道为什么它有两种类型的函数定义:

使用def定义在模块中的函数,使用myfunction(param1, param2)调用 使用fn定义的匿名函数,使用myfn调用。(param1 param2)

Only the second kind of function seems to be a first-class object and can be passed as a parameter to other functions. A function defined in a module needs to be wrapped in a fn. There's some syntactic sugar which looks like otherfunction(&myfunction(&1, &2)) in order to make that easy, but why is it necessary in the first place? Why can't we just do otherfunction(myfunction))? Is it only to allow calling module functions without parenthesis like in Ruby? It seems to have inherited this characteristic from Erlang which also has module functions and funs, so does it actually comes from how the Erlang VM works internally?

有两种类型的函数并从一种类型转换为另一种类型以便将它们传递给其他函数有任何好处吗?使用两种不同的表示法调用函数是否有好处?


当前回答

Fn ->语法用于使用匿名函数。使用var.()只是告诉elixir,我想让你使用带有func的var并运行它,而不是将var引用为仅保存该函数的东西。

Elixir有一个常见的模式,在这个模式中,我们没有在函数内部使用逻辑来查看应该如何执行,而是根据我们拥有的输入类型来匹配不同的函数。我认为这就是为什么我们在function_name/1的意义上使用arity来引用事物的原因。

习惯使用简写函数定义(func(&1)等)有点奇怪,但当您尝试管道或保持代码简洁时很方便。

其他回答

Elixir为函数提供了可选的花括号,包括圆整度为0的函数。让我们看一个例子,为什么单独的调用语法很重要:

defmodule Insanity do
  def dive(), do: fn() -> 1 end
end

Insanity.dive
# #Function<0.16121902/0 in Insanity.dive/0>

Insanity.dive() 
# #Function<0.16121902/0 in Insanity.dive/0>

Insanity.dive.()
# 1

Insanity.dive().()
# 1

如果不区分这两种类型的功能,我们就不能说什么是Insanity。Dive意味着:获取一个函数本身,调用它,或者也调用结果匿名函数。

只有第二种函数似乎是一类对象,可以作为参数传递给其他函数。模块中定义的函数需要封装在fn中。有一些语法糖,看起来像otherfunction(myfunction(&1, &2)),为了使这更容易,但为什么它是必须的?为什么我们不能只使用其他函数(myfunction) ?

您可以执行其他函数(&myfunction/2)

由于elixir可以执行不带括号的函数(如myfunction),使用otherfunction(myfunction)),它将尝试执行myfunction/0。

因此,您需要使用捕获操作符并指定函数,包括arity,因为您可以使用相同名称的不同函数。因此,myfunction / 2。

我不知道这对其他人是否有用,但我最终理解这个概念的方式是意识到长生不老药函数并不是函数。

elixir中的一切都是一种表达。所以

MyModule.my_function(foo) 

不是函数,而是执行my_function中的代码返回的表达式。实际上只有一种方法可以获得一个可以作为参数传递的“函数”,那就是使用匿名函数符号。

fn或&符号很容易被称为函数指针,但实际上它的作用远不止于此。这是对周围环境的封闭。

如果你问自己:

在这里,我需要一个执行环境还是一个数据值?

如果你需要使用fn执行,那么大部分的困难就会变得很大 清晰。

Fn ->语法用于使用匿名函数。使用var.()只是告诉elixir,我想让你使用带有func的var并运行它,而不是将var引用为仅保存该函数的东西。

Elixir有一个常见的模式,在这个模式中,我们没有在函数内部使用逻辑来查看应该如何执行,而是根据我们拥有的输入类型来匹配不同的函数。我认为这就是为什么我们在function_name/1的意义上使用arity来引用事物的原因。

习惯使用简写函数定义(func(&1)等)有点奇怪,但当您尝试管道或保持代码简洁时很方便。

在elixir中,我们使用def来简单地定义函数,就像我们在其他语言中所做的那样。 Fn创建一个匿名函数,请参考此说明