3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

ElixirAdvent Calendar 2024

Day 1

Elixirチートシートを作ろう、番外編その1 Elixir イミュータブルについて、誤解していたお話

Posted at

1. Over View

どもども、Elixirチートシートを作ろう、番外編その1であります

Elixir イミュータブルについて、誤解していたと思うのでまとめてみました。

2. さて、本題

変数は、僕の知る他の言語のように変数に割り当てられたメモリが書き換わらないだけ、と考えていたのですが、大きな考え違いをしている気がしてきました。

イミュータブルなのは、変数ではなくて、値自体だと考え直しました。

なので、普通のプログラミング言語のように、a = a + 1のような処理はできますが、これは、aのバインド先が変わるだけなので、どんどんメモリ上に結果が1, 2, 3, ...と増えていきます。

例1)

行番号 命令
1 A = 1
2 A = A + 1

この場合、1行目で、Aと1という値がバインドされる。2行目で、A + 1の結果である2とバインドされる。

C言語のように、変数Aのために確保されたメモリ領域が書き換わるわけではない。

ここまでで、ずいぶんと非効率だな、と頭を悩ませていたのですが、値はすべて書き換わらないのだから、これはリストなどを処理するのには、逆に効率が良い。

例2)
[2, 3] -> この値の先頭に、1を追加する場合は、以下のように書きます。

iex(23)> b = [2, 3]
[2, 3]
iex(24)> b = [1] ++ b
[1, 2, 3]

こいつを命令単位にバラすと、以下の様になります。

行番号 命令
1 b = [2, 3]
2 b = [1] ++ b

※List.insert_at(b, 0, 1)でも一緒

1行目の処理を終えた後、2行目では、変数bに、新たに1, 2, 3というリストをコピーすると考えて、非常に効率が悪い気がしていたのですが、実際には、リスト[2, 3]の先頭に要素1を加えたリストにバインドするだけだと気づきました。

変更前のbのリスト型の構造

変数 中身
b [2, 3]
bのhd 2にバインドされている
bのtl 3にバインドされている

変更後のbのリスト型の構造

計算の右辺の結果が、以下のリストとして作られる。

変数 中身
hd 1にバインドされる
tl [2, 3](今までのb)にバインド

b = [1] ++ bと書いているので、このリストが、bにバインドされ直す。

変数 中身
b [1, 2, 3]

要するに、LISTの中身をbindしている先を切り替えるだけで、別にlistを再作成しているわけでもない。
イミュータブルなおかげで、少ない手数でリストがコピーできるので、ガンガン、 b = [1] ++ bと書いてよいのだな開き直りました。

補足)ついでに、Elixirでは、リストの先頭に挿入する方が、コストが安い。

3
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?