函数行为不一致

时间:2013-06-08 07:11:12

标签: elixir

我正在尝试squarecube功能。 为什么squarecube爆炸时有效?

square = &1 * &1
square.(5)

正常工作

cube = &1 * &1 * &1
cube.(5)

抛出

** (ArithmeticError) bad argument in arithmetic expression
    :erlang.*(#Function<erl_eval.6.82930912>, 5)
    erl_eval.erl:572: :erl_eval.do_apply/6
    src/elixir.erl:133: :elixir.eval_forms/3
    /private/tmp/elixir-OVih/elixir-0.8.2/lib/iex/lib/iex/server.ex:19: IEx.Server.do_loop/1

3 个答案:

答案 0 :(得分:55)

0.10.3开始,您需要将部分应用程序放在括号之间,并以&运算符开头。

此版本不会有任何问题:

iex> square = &(&1 * &1)
iex> square.(5)
25
iex> cube = &(&1 * &1 * &1)
iex> cube.(5)
125

答案 1 :(得分:44)

在elixir-talk邮件列表上引用Alexei Sholik:

  

通常,&amp; 1只将其所属的原始表达式作为函数。换句话说,它将AST传递给第一个父级,并用fn替换该父级。

这样的表达很好用:

&1 * &1
&1 + 2
&1 * &2

但它不能涉及更复杂的表达。

例如,当你写:

&1 * &1 * &1

...你正在写一些类似于:

的东西
fn x -> fn x -> x * x end * x end

关于elixir-core的讨论是关于&1的行为是否需要修改,以免在这些情况下造成混淆。

要回答您的具体问题,您需要更多类似的内容:

cube = fn x -> x * x * x end

如果您想使用&1,可以使用math.pow/2的简单表达式:

cube = :math.pow(&1, 3)

...请注意,math.pow/2总是返回浮动。

答案 2 :(得分:2)

根据最新的Elixir documentation,有两种方法可以创建匿名函数:

# first one, more explicit
cube = fn x -> x * x * x end

#second one, syntactic sugar applied
cube = &(&1*&1*&1)

#calling them is the same
IO.puts cube.(8) # should be 512