34

Attualmente sta cercando di capire l'operatore "^" in Elisir. Dal sito web:Qual è l'operatore "pin" per e sono mutabili le variabili Elixir?

Il perno operatore^può essere utilizzato quando non v'è alcun interesse a rebinding una variabile, ma piuttosto in corrispondenza con il suo valore prima della partita:

Source - http://elixir-lang.org/getting_started/4.html

Con questo in mente, è possibile collegare un nuovo valore ad un simbolo in questo modo:

iex> x = 1 # Outputs "1" 
iex> x = 2 # Outputs "2" 

Posso anche fare:

iex> x = x + 1 # Outputs "3"! 

Quindi la mia prima domanda è; Le variabili Elixir sono mutabili? Sembra proprio che sia così ... Non dovrebbe essere possibile in un linguaggio di programmazione funzionale?

Così ora veniamo al gestore "^" ...

iex> x = 1 # Outputs "1" 
iex> x = 2 # Outputs "2" 
iex> x = 1 # Outputs "1" 
iex> ^x = 2 # "MatchError" 
iex> ^x = 1 # Outputs "1" 

penso che l'effetto di "^" è quello di bloccare "x" per l'ultimo valore rilegata ad esso. È tutto lì? Perché non assicurarti che tutte le "corrispondenze"/assegnazioni siano immutabili come Erlang stesso?

Stavo abituando a che ...

+2

È solo ombreggiato dopo la riassegnazione. I dati sono ancora immutabili. Un esempio di chiusura dal [blog di Joe Armstrong] (http://joearms.github.io/2013/05/31/a-week-with-elixir.html) dovrebbe chiarire. Secondo me è confuso. –

+0

Penso che a un certo punto abbiamo bisogno di aggiungere qualcosa ai documenti Elixir per spiegare questo dato che questa domanda si presenta regolarmente. –

+2

Capisco che l'operatore^sia necessario per eseguire una corrispondenza di pattern e un assegnamento sul termine sinistro. Ciò che per me non è chiaro è perché il comportamento predefinito sia "shadowing/re-assigning" piuttosto che pattern matching: - Nel mio codice ho davvero pochissima necessità di riassegnare; - In un codice che afferma di avere dati immutabili, mi aspetterei che la riassegnazione sia esplicita. – Pascal

risposta

45

I dati in Elixir è ancora immutabile, ma ci sono un paio di scorciatoie, che permettono di digitare meno o non preoccuparsi di trovare nuovi nomi. In Erlang, si poteva vedere spesso codice come questo:

SortedList = sort(List), 
FilteredList = filter(SortedList), 
List3 = do_something_with(FilteredList), 
List4 = another_thing_with(List3) 

In Elixir, si può solo scrivere:

list = sort(list) 
list = filter(list) 
list = do_something_with(list) 
list = another_thing_with(list) 

Questo è esattamente lo stesso, ma sembra un po 'meglio. Naturalmente le migliori soluzioni sarebbe quella di scrivere in questo modo:

list |> sort |> filter |> do_something |> another_thing_with 

Ogni volta, si assegna cosa nuova per list variabile, si ottiene nuova istanza:

iex(1)> a = 1 
1 
iex(2)> b = [a, 2] 
[1, 2] 
iex(3)> a = 2 
2 
iex(4)> b 
[1, 2] # first a did not change, it is immutable, currently a just points to something else 

hai appena detto, che non sei più interessato al vecchio a e lascia che punti a qualcos'altro. Se provieni dallo sfondo di Erlang, probabilmente conosci la funzione f dalla shell.

A = 1. 
f(A). 
A = 2. 

In Elixir proprio non c'è bisogno di scrivere il f. È fatto automaticamente per te. Ciò significa che ogni volta che si ha una variabile sul lato sinistro della corrispondenza del modello, si assegna un nuovo valore ad esso.

Senza l'operatore ^, non sarebbe possibile avere una variabile sul lato sinistro della corrispondenza del modello, perché otterrebbe un nuovo valore dal lato destro.^ significa non assegnare nuove cose a questa variabile - trattarla come valore letterale.

Ecco perché in Elixir

x = 1 
[1, x, 3] = [1, 2, 3] 

è equivalente in Erlang a:

X = 1, 
[1, CompletelyNewVariableName, 3] = [1, 2, 3] 

e:

x = 1 
[1, ^x, 3] = [1, 2, 3] 

è equivalente a:

x = 1 
[1, 1, 3] = [1, 2, 3] 

che in Erlang è:

X = 1, 
[1, X, 3] = [1, 2, 3] 
+0

Preferisco dire 'x = 1; [1, x, 3] = [1, 2, 3] 'è equivalente al seguente in Erlang:' X = 1. f (X). [1, X, 3] = [1, 2, 3] ' –

+2

Nella shell - sì, ma puoi usare questo anche negli script, dove' f/1' non è possibile, per questo l'ho confrontato con la creazione nuova variabile. – tkowal

19

dati in elisir è immutabile, anche se le variabili sono ri-assegnabile. Ciò che può rendere l'elisir leggermente confuso è l'assegnazione combinata e la corrispondenza del modello che stai vedendo.

Quando si utilizza il segno di uguale con un riferimento variabile sull'elisir sinistro, il primo modello corrisponde alla struttura e quindi esegue un assegnamento. Quando si ha solo un unico riferimento variabile sulla sinistra, si abbinerà qualsiasi struttura e così sarà assegnato in questo modo:

a = 1 # 'a' now equals 1 
a = [1,2,3,4] # 'a' now equals [1,2,3,4] 
a = %{:what => "ever"} # 'a' now equals %{:what => "ever"} 

Quando si dispone di una struttura più complessa sul elisir sinistra in primo modello abbinamento alle strutture, quindi eseguire il compito.

[1, a, 3] = [1,2,3] 
# 'a' now equals 2 because the structures match 
[1, a] = [1,2,3] 
# **(MatchError)** because the structures are incongruent. 
# 'a' still equals it's previous value 

Se si vuole valorizzare partita contro il contenuto di una variabile è possibile utilizzare il pin '^':

a = [1,2] # 'a' now equals [1,2] 
%{:key => ^a} = %{:key => [1,2]} # pattern match successful, a still equals [1,2] 
%{:key => ^a} = %{:key => [3,4]} # **(MatchError)** 

Questo esempio forzato potrebbe anche essere stato scritto con 'a' sulla destra lato e senza il perno:

%{:key => [1,2]} = %{:key => a} 

Ora dicono che si voleva assegnare una variabile a parte di una struttura, ma solo se fanno parte di quella struttura ha trovato qualcosa memorizzato in 'a', in elisir questo è banale:

a = %{:from => "greg"} 
[message, ^a] = ["Hello", %{:from => "greg"}] # 'message' equals "Hello" 
[message, ^a] = ["Hello", %{:from => "notgreg"}] # **(MatchError)** 

In questi semplici esempi l'uso della corrispondenza perno ed il modello non è immediatamente super-prezioso, ma come si impara di più elisir e iniziare il pattern matching sempre più diventa parte della espressività che elisir offre.

+0

risposta migliore! - vai Greg – metakungfu

Problemi correlati