Поведение непоследовательных функций
Я пытаюсь выполнить функцию square
и cube
.
Почему square
работает во время cube
?
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
Ответы
Ответ 1
Цитата Алексея Шолика в списке рассылки эликсира:
Обычно, 1 только вносит в функцию примитивное выражение, которому он принадлежит. Другими словами, он поднимает AST до первого родителя и заменяет этого родителя на fn.
Выражения вроде этой работы очень хорошо:
&1 * &1
&1 + 2
&1 * &2
Но он не может быть вовлечен в более сложное выражение.
Например, когда вы пишете:
&1 * &1 * &1
... вы пишете нечто похожее на:
fn x -> fn x -> x * x end * x end
Обсуждение эликсир-ядра о том, нужно ли изменять поведение &1
, чтобы быть менее запутанным в этих случаях.
Чтобы ответить на ваш конкретный вопрос, вам нужно что-то большее:
cube = fn x -> x * x * x end
Если вы хотите использовать &1
, вы можете использовать простое выражение с math.pow/2
:
cube = :math.pow(&1, 3)
... обратите внимание, что math.pow/2
всегда возвращает float.
Ответ 2
Так как 0.10.3 вам нужно поставить частичное приложение между круглыми скобками, которым предшествует оператор &
.
У вас не будет проблем с этой версией:
iex> square = &(&1 * &1)
iex> square.(5)
25
iex> cube = &(&1 * &1 * &1)
iex> cube.(5)
125
Ответ 3
В соответствии с последней документацией существует два способа создания анонимных функций:
# 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