Подтвердить что ты не робот

Поведение непоследовательных функций

Я пытаюсь выполнить функцию 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
4b9b3361

Ответ 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