LoginSignup
9
2

More than 5 years have passed since last update.

Elixirの"for"はリストのジェネレータ

Last updated at Posted at 2018-09-18

Elixir

みなさんElixir知ってますか!?
え?知らない?じゃあまずこれを・・・笑
【fukuoka.ex】学生エンジニアがElixirに興味を持ったきっかけと初心者にオススメの勉強法

前置きはおいといて、今回はスクリプト言語になれていると引っかかるであろう「関数型言語」Elixirのforの動作について共有しようと思います。

やりたかったこと

Elixirの勉強のためにHackerRankのこの問題を解いているときに、文字列から「各文字を最後尾にずらしたリスト」を生成することをチャレンジしていました。
Rotate String | HackerRank

abc -> ["bca", "cab", "abc"]

Elixirのforの動作

さて、ここで問題ですが、fの値ってどうなると思います?

f = for i <- 0..3, do: i*2

・・・実はfの値は「リスト」になります。

実行結果
[0, 2, 4, 6]

これってちょっとモヤモヤしませんか?(わたしはモヤモヤしましたw)

Pythonで同様のことをしようとすると[]で囲まないといけないですよね?

f = [i*2 for i in range(4)]

そもそも関数型であるElixirと一般的なスクリプト言語ではforの意味が異なります。

内包表記 · Elixir School

最初に気づくのは for とジェネレータの使い方です。ジェネレータとは何でしょうか。リスト内包表記の x <- [1, 2, 3, 4] といった式のことです。次の値を生成する責任を負っています。
幸い、内包表記はリストだけに限定されず、実際列挙可能なものならどんなものにでも使えます

関数型でリストに対して繰り返し処理したい場合はEnum.mapを使うのがポイントみたいです!

文字列から「各文字を最後尾にずらしたリスト」の実装

これらを踏まえると冒頭の、文字列から「各文字を最後尾にずらしたリスト」は以下のように実装出来ます。

    def get_rotations(s) do
        s = String.codepoints(s) # 1文字ずつ区切って配列にする
        for i  <- 1..length(s) do
            {left, right} = Enum.split(s, i)
            Enum.join(right ++ left)
        end
    end

関数の帰り値がforで終わるという感覚が関数型らしいですね

関数型を学ぶときは今までの常識はいったん忘れる

関数型言語はなるべく状態を持たずにデータの入出力関係を記述して目的を達成することを目指します。
そのため、状態を持つオブジェクト指向言語の考え方とは異なります。
個人的にはシェルスクリプトの感覚と近いのではないかなぁと思います。
(シェルスクリプトもオブジェクト指向言語との違いで苦手になる人多いっぽくて、こんな記事あるみたいですがwプログラマーの君! 騙されるな! シェルスクリプトはそう書いちゃ駄目だ!! という話

オブジェクト指向に慣れているととっつきにくいですが、テストがしやすかったり状態を持たないことで並列実行しやすかったりと、関数型言語のメリットも結構あります。
それに関数型言語を1つ極めておくと、他の関数型言語さわる時にいいと思うので学生さんとか是非やってみてください!

9
2
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
9
2