2013-06-08 3 views
39

Sto provando un square e una funzione cube. Perché lo square funziona mentre cube esplode?Comportamento incoerente delle funzioni

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

funziona bene, mentre

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

Lanci

** (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 
+2

A cura il tag 'Erlang' da questo post. È più per la gente Elixir. –

risposta

44

Citando Alexei Sholik sul elisir-talk mailing list:

Normalmente, & 1 fa solo in una funziona il primitivo expressi su di esso appartiene. In altre parole, porta l'AST al primo genitore e sostituisce quel genitore con un fn.

Espressioni come questo lavoro bene:

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

Ma non può essere coinvolto in un'espressione più complicata.

Per esempio, quando si scrive:

&1 * &1 * &1

... si scrive qualcosa di simile a:

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

c'è discussione sul elisir-core sul fatto che il comportamento di &1 esigenze di essere modificato per essere meno confusionario in questi casi.

Per rispondere alla tua domanda specifica, però, si desidera qualcosa di più simile a questo:

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

Se si desidera utilizzare &1, è possibile utilizzare una semplice espressione con math.pow/2:

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

. .. notate che math.pow/2 restituisce sempre un float.

+0

più uso l'elisir, più sento che gli sviluppatori non sanno come scrivere un parser. – PPPaul

53

Dal 0.10.3 è necessario mettere l'applicazione parziale tra parentesi preceduta dall'operatore &.

Non avrete alcun problema con questa versione:

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

+1 - OP @Benjamin Tan - leggi http://pragprog.com/book/elixir/programming-elixir per l'ultimo – Vatsala

2

Secondo l'ultimo Elixir documentation ci sono due modi per creare funzioni anonime:

# 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