我正在学习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?
有两种类型的函数并从一种类型转换为另一种类型以便将它们传递给其他函数有任何好处吗?使用两种不同的表示法调用函数是否有好处?
我不知道这对其他人是否有用,但我最终理解这个概念的方式是意识到长生不老药函数并不是函数。
elixir中的一切都是一种表达。所以
MyModule.my_function(foo)
不是函数,而是执行my_function中的代码返回的表达式。实际上只有一种方法可以获得一个可以作为参数传递的“函数”,那就是使用匿名函数符号。
fn或&符号很容易被称为函数指针,但实际上它的作用远不止于此。这是对周围环境的封闭。
如果你问自己:
在这里,我需要一个执行环境还是一个数据值?
如果你需要使用fn执行,那么大部分的困难就会变得很大
清晰。
我一直不明白为什么对此的解释如此复杂。
这实际上只是结合了ruby风格的“不带paren的函数执行”的实际情况的一个非常小的区别。
比较:
def fun1(x, y) do
x + y
end
To:
fun2 = fn
x, y -> x + y
end
虽然这两个都只是标识符……
Fun1是一个描述用def定义的命名函数的标识符。
Fun2是描述变量(恰好包含对函数的引用)的标识符。
当你在其他表达式中看到fun1或fun2时,这意味着什么?在计算该表达式时,是调用引用的函数还是只是引用内存外的值?
在编译时没有很好的方法知道。Ruby可以自省变量名称空间,以查明变量绑定是否在某个时间点遮蔽了函数。Elixir正在编译,不能真正做到这一点。这就是点符号的作用,它告诉Elixir它应该包含一个函数引用,并且应该调用它。
这真的很难。假设没有点符号。考虑下面的代码:
val = 5
if :rand.uniform < 0.5 do
val = fn -> 5 end
end
IO.puts val # Does this work?
IO.puts val.() # Or maybe this?
根据上面的代码,我认为很清楚为什么你必须给Elixir提示。想象一下,如果每个变量去引用都必须检查一个函数?或者,想象一下,总是推断变量解引用使用的是函数需要什么样的英雄主义?