为什么需要Elixir Capture操作符将函数绑定到值
我有以下elixir代码片段:为什么需要Elixir Capture操作符将函数绑定到值,elixir,Elixir,我有以下elixir代码片段: defmodule Rectangle do def area(a, b) do a * b end def area(a) do a * a end end 然后我将文件加载到iex会话中,如下所示: iex(1)> import_file "rectangle.exs" {:module, Rectangle, <<70, 79, 82, 49, 0, 0, 5, 84
defmodule Rectangle do
def area(a, b) do
a * b
end
def area(a) do
a * a
end
end
然后我将文件加载到iex会话中,如下所示:
iex(1)> import_file "rectangle.exs"
{:module, Rectangle,
<<70, 79, 82, 49, 0, 0, 5, 84, 66, 69, 65, 77, 69, 120, 68, 99, 0, 0, 0, 204, 131, 104, 2, 100, 0, 14, 101, 108, 105, 120, 105, 114, 95, 100, 111, 99, 115, 95, 118, 49, 108, 0, 0, 0, 4, 104, 2, ...>>,
{:area, 1}}
现在我想将arity为1的面积函数分配给匿名函数,如:
iex(3)> fun = Rectangle.area/1
** (UndefinedFunctionError) undefined function Rectangle.area/0
Rectangle.area()
但当我打字时,我喜欢:
iex(3)> fun = &Rectangle.area/1
&Rectangle.area/1
然后它就起作用了。为什么elixir期望&在函数名前面,尽管Rectangle.area已经是一个函数了?这是因为编译器就是这样解析函数的
Rectangle.area/1
将解析为Rectangle.area
到1
(因此未定义函数Rectangle.area/0
错误)
您可以使用以下命令查看表达式的解析方式:
这只是一个语法问题——它对解释器说,“指向函数的指针”不是代数表达式(例如,形式错误的除以1)。记住Elixir在做“杂技”以保持与Erlang的兼容性-因此必须做出一些妥协-我认为。@GavinBrelstaff这实际上有两个原因。第一个原因是,在Elixir语法中,参数是可选的,引用函数只会调用它,除非使用
&
表示命名函数和arity(它使用的参数数量)。第二个原因是Elixir没有做任何杂技来维护与Erlang的兼容性,它只是假设Erlang的所有语义。在Beam VM中,函数通过名称和算术来标识。同一个名字加上两个算术实际上是两个不同的函数。谢谢asonge-我也是来学习的!尽管如此,允许括号在任何时候都是可选的,这对我们用户来说都是很好的,但对那些维护该语言的人来说,这是一个挑战,“杂技”与否。关于不同类型函数的良好解释可以看一下,除法与函数的关系是什么?@zero_编码,这是arity-@zero_编码,除法不应用于函数,而是应用于函数返回的值。在Elixir(与Ruby类似)中,括号对于无参数函数是可选的:Rectangle.area
与Rectangle.area()相同。因此,编译器尝试在矩形
中找到一个没有参数的函数区域
,并应用它。另一种形式,&Rectangle.area/1
告诉编译器搜索带有一个参数的函数Rectangle.area
,或者如@arathunku所指出的那样,使用arity 1。
iex(3)> fun = &Rectangle.area/1
&Rectangle.area/1
iex> quote do &Rectangle.area/1 end
iex> quote do Rectangle.area/1 end