Question

I'm trying out a square and a cube function. Why does square work while cube blows up?

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

Works fine while

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

Throws

** (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
Was it helpful?

Solution 2

Quoting Alexei Sholik on the elixir-talk mailing list:

Normally, &1 only makes into a function the primitive expression it belongs to. In other words, it walks up the AST to the first parent and replaces that parent with a fn.

Expressions like this work just fine:

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

But it can't be involved in a more complicated expression.

For instance, when you write:

&1 * &1 * &1

... you're writing something akin to:

fn x -> fn x -> x * x end * x end

There's discussion on elixir-core about whether the behavior of &1 needs to be modified to be less confusing in these cases.

To answer your specific question, though, you want something more like this:

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

If you want to use &1, you can use a simple expression with math.pow/2:

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

... note that math.pow/2 always gives back a float.

OTHER TIPS

Since 0.10.3 you need to put the partial application between parentheses preceded by the & operator.

You won't have any trouble with this version:

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

According to the latest Elixir documentation there are two ways to create anonymous functions:

# 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
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top