Skip to content

Instantly share code, notes, and snippets.

@koga1020
Last active December 5, 2020 05:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save koga1020/079e09db0a8b19274a506b35d0ad0c35 to your computer and use it in GitHub Desktop.
Save koga1020/079e09db0a8b19274a506b35d0ad0c35 to your computer and use it in GitHub Desktop.

赤いカプセルを取れ

プログラミング言語Elixirは、不変的な状態を用いた関数プログラミングと、並行性へのアクターベースのアプローチを、整然とした、モダンな文法の中にラップしたものだ。そして、業務に耐えうる頑健さを持ち、高性能で、分散可能なErlang VM上で動作する。でも、いったいこれって、どういう意味だろう?

これは、今あなたの時間を奪っている。諸々の難しいことについての心配を、やめていいってことだ。もう、マルチスレッド環境でデータの一貫性を守るために頭を絞る必要はない。アプリケーションをどうスケールさせるか、あまり考えなくてよくなる。さらに、これが一番大事なことだが、プログラミングを別のやり方で考えることができるようになる。

point:

  • 「プログラミングを別のやり方で考えることができるようになる」がポイント
  • マトリックスに「赤いカプセル」ってのが出てくる(らしい)
    • 「赤いカプセルを飲めば、真実を見ることができる?」的な?

1.1 プログラミングはデータの変換をするものだ

point:

  • オブジェクト指向だと現実の世界をモデル化しようとするよね
  • データの状態をインスタンスに隠蔽する
  • オブジェクトの状態をひたすら考えるが、仕事を済ませたいのであって、状態を維持したいわけではない
    • この表現いいよねw
  • 我々がやりたいことはデータ変換
    • コンピュータの空ファイル→文章の入った形に変換する
    • Webサーバーへのリクエスト→ファイルのダウンロード処理(Responseへ変換)
  • データを隠蔽したいのではない、変換したいんだ。

もしあなたがオブジェクト指向の世界から来たのなら、クラスやそのオブジェクトの観点から考えるのに慣れているだろう。クラスや振る舞いを定義し、オブジェクトは状態を持つ。開発者は、問題をモデル化しようとする。入り組んだクラスの階層構造を考え出すのに時間をかける

(中略)

でも、これは現実の世界ではない。現実の世界では、抽象的な階層構造をモデル化したいわけではない(なぜなら、実際には、真の階層構造なんてそう多くはないからだ)

パイプラインで変換を組み合わせる

point:

Unixユーザーは、小さく、焦点を合わせた、どのようにでも組み合わせられるコマンドラインツール、という哲学に慣れ親しんでいる。それぞれのツールは入力をとり、それを変換し、次のツール(もしくは人間)が利用できる形式で結果を出力する

関数はデータ変換器

point:

  • データ変換を担うもの = 関数
  • 関数プログラミングを学ぶと、そもそもの考え方が変わってくる

Elixirでの問題の解き方は、Unixシェルと同様だ。コマンドラインユーティリティの代わりに、関数がある。驚くほど簡単に、関数同士をつなげることができる。関数をより小さく、より焦点を合わせた形にすればするほど、つなげる際の柔軟性は高まる。

(中略)

この「変換」、関数は入力を出力に変換するものという考え方は、関数プログラミングの中心に位置している。三角関数の sin を例にとってみよう。 π/4 を受け取ると0.7071...を返す。HTMLテンプレートシステムも関数だ。プレースホルダーを含むテンプレートと、名前付きの値リストを受け取り、完全なHTMLドキュメントを生成する

2章

コードだけ抜粋

iex> list = [1, 2, 3]
[1, 2, 3]
iex> [a, b, c] = list
[1, 2, 3]
iex> a
1
iex> b
2
iex> c
3

リストのネストのパターン

iex> list = [1, 2, [ 3, 4, 5 ]]
[1, 2, [ 3, 4, 5 ]
iex> [a, b, c] = list
[1, 2, [ 3, 4, 5 ]
iex> a
1
iex> b
2
iex> c
[ 3, 4, 5 ]

一部だけマッチさせるパターン

iex> list = [1, 2, 3]
[1, 2, 3]
iex> [a, 2, b] = list
[1, 2, 3]
iex> a
1
iex> b
3

エラー

iex> list = [1, 2, 3]
[1, 2, 3]
iex> [a, 1, b] = list
** (MatchError) no match of right hand side value: [1, 2, 3]

2.3 _ (アンダースコア)で値を無視する

iex> [1, _, _] = [1, 2, 3]
[1, 2, 3]
iex> [1, _, _] = [1, "cat", "dog"]
[1, "cat", "dog"]

2.4. 変数の束縛は(マッチの中で)一度だけ

iex> [a, a] = [1, 1]
[1, 1]
iex> a
1
iex> [a, a] = [1, 2]
** (MatchError) no match of right hand side value: [1, 2]

これだと新しい値に束縛される

iex> a = 1
1
iex> [1, a, 3] = [1, 2, 3]
[1, 2, 3]
iex> a
2

ピン演算子を使うと、既存の値を使う

iex> a = 1
1
iex> a = 2
2
iex> ^a = 1
(MatchError) no match of right hand side value: 1

2.5 等号記号の別の見方

  • Erlangでの等号記号を、代数での等号記号の使われ方に例える
  • x = a + 1 と書いた時、a + 1の値をxに代入したリはしない
  • 単に、式xとa+1は同じ値と表明しているだけ

練習問題

PatternMatching-2

どれがマッチする?

  • [a, b, a] = [1, 2, 3]
  • [a, b, a] = [1, 1, 2]
  • [a, b, a] = [1, 2, 1]

PatternMatching-3

変数aがもともと2であるとき、どれがマッチする?

  • [a, b, a] = [1, 2, 3]
  • [a, b, a] = [1, 1, 2]
  • a = 1
  • ^a = 2
  • ^a = 1
  • ^a = 2 - a
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment