【Elixir】プログラミングElixirをまとめてみる
こんにちは、しきゆらです
今回は、プログラミングElixirという本を買ったので内容をさらっとまとめてみます
(頑張って公式サイトを翻訳しながら進めていたのが今年初めと知ってビビる昨今・・・)
この本については、るびま0054号でも紹介されているのでそちらも参照のこと
この本は?
単なるElixirの文法を学ぶための本・・・というわけではなく
Elixirとはどんな言語なのか、どういう風に考えられているのか
ということを実際にコードを交えながら知ることができる本となっています
本の中でも
この本は、Elixirをて上から下まで網羅したリファレンスガイドではない。
と書かれています
もちろん、本の中で文法等にも触れられていますのでまったくElixirのことを知らなくても読むことができるようになっています
現在は2章まで読みました
まだまだ知らないことばかりですが文法の部分をまとめていきます
パターンマッチ
まず、Elixirはいわゆる関数プログラミング言語という部類の言語になっています
私はこれまで手続き型のCやオブジェクト指向のJavaやRubyを触ったことがありますが
新しい分野です
初めに書かれているのはパターンマッチについて
では、コードをiexで実行しながら進めていきます
なお、ここでいう行数はiex()の中の数字のことを指すとします
iex(1)> hoge = 1 1 iex(2)> hoge + 4 5
これだけでは、普通の言語となんら変わりないです
もっと見てみます
iex(3)> hoge = 2 2 iex(4)> 2 = hoge 2 iex(5)> 3 = hoge ** (MatchError) no match of right hand side value: 2
こちら
4行目を見ると、「2 = hoge」と書いてますね
Elixirの「=」は代入ではなくパターンマッチを行っているんですね
右辺と左辺がマッチすればマッチしたものが返り、そうでない場合はMatchErrorが返ると
hogeは変数です
3行目のような動作を「束縛する」と言いますね
hogeという変数に3という数字を束縛するとマッチングが成功しますね
このように、「=」はマッチするように変数の値を変えるわけです
はたから見れば代入のようです
なお、変数に値を束縛するときは代入と同じように「変数 = 束縛するもの」という形にしなければいけません
5行目は、hogeを3に束縛すればマッチしそうですが
Elixirは束縛するときは、変数を左側に置くというルールがあるのでそうならないんですね
リストとは
進む上で、「リスト」いうものを導入します
角括弧([])の中に、カンマ区切りで値を並べたものをリストといいます
["hoge", "fuga", "piyo"] ["今日も", "1日",["頑張る", "ぞい!"]]
Rubyの配列のようですね
では、リストとマッチさせてみます
iex(6)> list = ["ねむみ", "はらへり", "つらいお"] ["ねむみ", "はらへり", "つらいお"]
listという変数と3つの文字列が入ったリストをマッチさせました
6行目により、変数listには右辺のリストが束縛されました
もちろん
iex(7)> ["ねむみ", "はらへり", "つらいお"] = list ["ねむみ", "はらへり", "つらいお"]
となります
では、これはどうでしょう
iex(8)> [sleep, hungry, hard] = list ["ねむみ", "はらへり", "つらいお"]
変数が3つ含まれたリストと変数listをマッチさせました
8行目では、listと左辺のリストがマッチするようにするにはどうすればいいかを考えてみます
要素の数が等しいので、それぞれの要素が等しくなればマッチしそうです
そうなると、左辺のそれぞれの変数に右辺の要素を一つづつ当てはめていけばマッチしますね
その結果が以下になります
iex(9)> sleep "ねむみ" iex(10)> hungry "はらへり" iex(11)> hard "つらいお"
このように、各変数に右辺の要素を当てはめ流ことでマッチしました
あとは、この辺を見てみるといいかと
iex(13)> [1,2,a] = list [1, 2, 3] iex(14)> a 3 iex(15)> [1,3,b] = list ** (MatchError) no match of right hand side value: [1, 2, 3]
ここでの変数listは[1,2,3]に束縛されています
13行目がマッチするためには、変数aにlistの3つ目の要素を束縛すればマッチしますね
14行目ではaに3が束縛されていることがわかります
では15行目はどうしてエラーが出ているんでしょう
ここでは、bにどんな値を束縛したとしても2つ目の要素が3なのでlistとはどう頑張ってもマッチしません
なのでエラーが出ているわけですね
なお、この場合bには何も束縛されません
特定の部分を無視する
マッチングを行うとき、特定の部分を無視したい場合はどうするんでしょうか
iex(16)> [1,_,_] = [1,2,3] [1, 2, 3] iex(17)> [1,_,_] = [1,5,9] [1, 5, 9]
16、17行目の左辺は全く同じ、右辺が異なっています
しかし、どちらもマッチしていますね
無視したい部分を「_」とすることでマッチングを行うことができます
この場合は、要素数が3で先頭に1があるリストならばマッチするようになっています
マッチ中の束縛は1回
iex(18)> [a,a] = [1,1] [1, 1] iex(19)> [a,a] = [1,2] ** (MatchError) no match of right hand side value: [1, 2]
18行目、左辺はaという変数が2つ含まれるリスト、右辺は1が2つ含まれるリストです
マッチするためには、aに1を束縛すればいいですね
では、19行目はどうでしょう
左辺の一つ目のaに1を束縛すれば、右辺の1つ目の要素とはマッチしそうです
2つ目のaには2を束縛すれば、右辺の2つ目の要素ともマッチしそう・・・
何てうまい話はないわけです
aに1を束縛すれば1と2はマッチしないのでエラーとなります
ルールとして、マッチ中に束縛するのは1回のみのようです
iex(20)> a = 1 iex(21)> a = 2
とすればaには1も2も束縛することができますが
1つのマッチングの中で束縛されるのは1回のみとなります
変数の束縛された値とのマッチング
変数に値を束縛するのではなく、束縛された値とマッチングを行う場合はどうするんでしょうか
iex(22)> a = 1 1 iex(23)> a = 2 2 iex(24)> ^a = 3 ** (MatchError) no match of right hand side value: 3
「^a」とすると、aに束縛された値とのマッチングを行います
24行目は、23行目で束縛された2と3のマッチングを行い、マッチしないのでエラーを返しています
マッチングに関しては以上です
これまで触ってきた言語とは動きが異なりますね
似た動きをする言語といてはPrologがありましたが、きちんと触れたわけではないのでなんともいえないです
取り合えず、こんな感じで少しずつElixirについて触れていくのでよろしくです
おわり