2016-05-25 37 views
6

Ho recentemente deciso di imparare l'elisir. Venendo da uno sfondo C++/Java/JavaScript ho avuto un sacco di problemi ad afferrare le basi. Questo potrebbe sembrare stupido, ma come funzionano le dichiarazioni di ritorno in Elixir? Ho guardato intorno e sembra come se è solo l'ultima riga di una funzione cioèValori di ritorno in elisir?

def Hello do 
    "Hello World!" 
end 

Sarebbe questo ritorno della funzione "Ciao Mondo!", C'è un altro modo per fare un ritorno? Inoltre, come faresti a tornare presto? in JavaScript potremmo scrivere qualcosa di simile per trovare se una matrice ha un certo valore in esso:

function foo(a){ 
    for(var i = 0;i<a.length;i++){ 
     if(a[i] == "22"){ 
     return true; 
     } 
    } 
    return false; 
} 

Come sarebbe che il lavoro in Elixir?

+1

Ecco un altro esempio su come tornare presto: http: //elixir-examples.github.io/esempi/return-early – Brandon

+0

@Brandon, grazie man, quindi in questo esempio se "some_condition" è false, verrà emesso il valore che emette "do_something()"? –

+0

Non è una domanda stupida. È davvero difficile abituarsi alla nozione di ogni funzione che restituisce l'ultimo valore calcolato quando si è abituati alle lingue imperative. Rimanere con esso - una volta abituati all'idea di ogni funzione che restituisce un valore, scoprirai che le tue funzioni diventeranno molto più coese. –

risposta

5

Elixir non ha alcuna parola chiave 'uscire' che sarebbe equivalente alla parola 'ritorno' in altre lingue .

In genere ciò che si farebbe è ricostruire il codice in modo che l'ultima istruzione eseguita sia il valore restituito.

Di seguito è un modo idiomatica in elisir di eseguire l'equivalente del tuo test codice, supponendo che si intende 'a' come qualcosa che si comporta tipo di matrice, come nel tuo esempio iniziale:

def is_there_a_22(a) do 
    Enum.any?(a, fn(item) -> item == "22" end.) 
end 

Che cosa sta realmente succedendo qui stiamo ristrutturando un po 'il nostro modo di pensare. Invece dell'approccio procedurale, in cui cercheremmo attraverso l'array e torneremmo presto se trovassimo quello che stavamo cercando, ci chiederemo in cosa consiste davvero nel frammento di codice: "Questo array ha un 22 dovunque?"

Quindi utilizzeremo la libreria di elisir Enum per eseguire attraverso l'array per noi e fornire la funzione any? con un test che ci dirà se qualcosa corrisponde ai criteri che ci interessavano.

Mentre questo è un caso che è facilmente risolvibile con l'enumerazione, penso che sia possibile che il cuore della tua domanda si applichi maggiormente a cose come il "modello di buttafuori" usato nei metodi procedurali. Ad esempio, se soddisfo determinati criteri in un metodo, restituisco subito. Un buon esempio di questo sarebbe un metodo che restituisce false se la cosa si sta andando a fare un lavoro su è nullo:

function is_my_property_true(obj) { 
    if (obj == null) { 
    return false; 
    } 
    // .....lots of code.... 
    return some_result_from_obj; 
} 

L'unico modo per raggiungere davvero questo elisir è quello di mettere la guardia di fronte e calcolare un metodo:

def test_property_val_from_obj(obj) do 
    # ...a bunch of code about to get the property 
    # want and see if it is true 
end 

def is_my_property_true(obj) do 
    case obj do 
    nil -> false 
    _ -> test_property_value_from_obj(obj) 
    end 
end 

tl; dr - No non c'è un equivalente - è necessario strutturare il codice di conseguenza. Il rovescio della medaglia, questo tende a mantenere i vostri metodi piccoli - e il vostro intento chiaro.

+0

Questo ha molto senso, grazie per averlo spiegato in tanti dettagli –

4

Si è corretto in quell'ultima espressione viene sempre restituita. Ancora di più - non ci sono dichiarazioni nella lingua - solo espressioni. Ogni costrutto ha un valore - if, case, ecc. Non è inoltre previsto un ritorno anticipato. Questo può sembrare limitante, ma ci si abitua velocemente.

un modo normale per risolvere il vostro esempio con Elixir sarebbe quella di utilizzare una funzione di ordine superiore:

def foo(list) do 
    Enum.any?(list, fn x -> x == "22" end) 
end 
+0

Grazie per la spiegazione, devo avvolgere la mia mente sull'eleganza di Elixir. –