現在、Elixirの「^」演算子を理解しようとしています。ウェブサイトから:
Pin演算子^は、変数を再バインドする必要がなく、一致する前の値と照合する場合に使用できます。
ソース- http://elixir-lang.org/getting_started/4.html
これを念頭に置いて、次のようにシンボルに新しい値をアタッチできます。
iex> x = 1 # Outputs "1"
iex> x = 2 # Outputs "2"
私もできます:
iex> x = x + 1 # Outputs "3"!
だから私の最初の質問は; Elixir変数は変更可能ですか?それは確かにそうであるように見えます...関数型プログラミング言語ではそれが可能ではないでしょうか?
それでは、「^」演算子に行きます...
iex> x = 1 # Outputs "1"
iex> x = 2 # Outputs "2"
iex> x = 1 # Outputs "1"
iex> ^x = 2 # "MatchError"
iex> ^x = 1 # Outputs "1"
「^」の効果は、「x」をそれにバインドされている最後の値にロックすることです。それで全部ですか?すべての「一致」/割り当てがErlang自体のように不変であることを確認しないでください。
慣れてきました...
Elixirのデータは依然として不変ですが、いくつかの省略形があり、入力を少なくしたり、新しい名前を見つけることを心配したりできません。 Erlangでは、次のようなコードがよく見られます。
SortedList = sort(List),
FilteredList = filter(SortedList),
List3 = do_something_with(FilteredList),
List4 = another_thing_with(List3)
Elixirでは、次のように書くことができます。
list = sort(list)
list = filter(list)
list = do_something_with(list)
list = another_thing_with(list)
これはまったく同じですが、少し良く見えます。もちろん、最善の解決策は次のように書くことです:
list |> sort |> filter |> do_something |> another_thing_with
毎回、list
変数に新しいものを割り当てると、新しいインスタンスが取得されます。
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
あなたは、古いa
にもう興味がなく、他の何かを指すようにすると言います。 Erlangのバックグラウンドを使用している場合は、シェルのf
関数をご存じでしょう。
A = 1.
f(A).
A = 2.
エリクサーでは、f
と書く必要はありません。自動的に行われます。これは、パターンマッチの左側に変数があるたびに、それに新しい値を割り当てることを意味します。
^
演算子がないと、右側から新しい値を取得するため、パターンマッチの左側に変数を置くことができません。 ^
はこの変数に新しいものを割り当てない-リテラル値として扱うを意味します。
だからエリクサーでは
x = 1
[1, x, 3] = [1, 2, 3]
erlangでは次と同等です:
X = 1,
[1, CompletelyNewVariableName, 3] = [1, 2, 3]
そして:
x = 1
[1, ^x, 3] = [1, 2, 3]
以下と同等です。
x = 1
[1, 1, 3] = [1, 2, 3]
erlangではこれは:
X = 1,
[1, X, 3] = [1, 2, 3]
Elixirのデータは不変ですが、変数は再割り当て可能です。エリクサーを少し混乱させるのは、表示されている割り当てとパターンマッチングの組み合わせです。
左側のエリクサーに変数参照がある等号を使用すると、最初に構造とパターンが一致し、次に割り当てが実行されます。左側に唯一の変数参照がある場合、それは任意の構造に一致するため、次のように割り当てられます。
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"}
左側のより複雑な構造がある場合、エリクサーは最初に構造にパターンマッチし、次に割り当てを実行します。
[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
変数の内容に対して値を一致させたい場合は、ピン '^'を使用できます。
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)**
この不自然な例は、右側に「a」を付けて、ピンなしで書くこともできます。
%{:key => [1,2]} = %{:key => a}
ここで、構造体の一部に変数を割り当てたいが、その構造体の一部が 'a'に格納されているものと一致した場合のみ、elixirではこれは簡単です。
a = %{:from => "greg"}
[message, ^a] = ["Hello", %{:from => "greg"}] # 'message' equals "Hello"
[message, ^a] = ["Hello", %{:from => "notgreg"}] # **(MatchError)**
これらの単純な例では、ピンマッチングとパターンマッチングの使用はすぐには価値がありませんが、エリクサーを学び、パターンマッチングを開始するにつれて、エリクサーが提供する表現力の一部になります。