Upgrade to Pro — share decks privately, control downloads, hide ads and more …

(Ruby使いのための)Scalaで学ぶ関数型プログラミング

 (Ruby使いのための)Scalaで学ぶ関数型プログラミング

Yuka O’oka

October 23, 2013
Tweet

More Decks by Yuka O’oka

Other Decks in Programming

Transcript

  1. Scala
    Scalaで学ぶ
    で学ぶ
    関数型プログラミング
    関数型プログラミング
    Ruby使いのための
    Presented by おおかゆか

    View Slide

  2. 自己紹介
    自己紹介
    おおかゆか (
    おおかゆか (id: oukayuka
    id: oukayuka)

    フリーランスのWebプログラマ。
    元々はPHPerでしたが、最近はもっぱらRails案件を
    生業に活動中。
    Scalaに手を出したのは、ほんの3ヶ月ほど前。
    エンジニアがお金について考えるためのrake:money
    rake:money
    という勉強会を主宰してます。月1の頻度で都内にて
    開催しているので、興味があればどうぞ。
    http://groups.google.co.jp/group/rakemoney

    View Slide

  3. Scalaって何?という方は、これを読
    む前にまず
    「Ruby使いのための
    Scalaのススメ」
    をご一読ください。
    ☞http://ja.verbmode.net/2009/10/03/
      recommend_of_scala_for_rubyist

    ≪注意≫
    注意≫

    View Slide

  4. Rubyは「acceptable Lisp」とか「MatzLisp」と
    揶揄されることもあるくらい、Lispからの影響
    が強い言語である。
    Ruby使いがより一歩ステップアップするため
    にLispを学ぼうとはよく言われるところ。
    Eric Raymond も Paul Grahamも、ことあるご
    とにLispを薦めてくる。
    しかしMatzも認めるように、Lispは普通の人
    には扱いきれない習得コストの高い言語。
    よい
    よいRuby
    Ruby使いになるために
    使いになるために

    View Slide

  5. それでもScalaなら…、Scalaならきっと何とかしてく
    れる。というのも、Scalaは最もRubyに似た関数型
    言語だから。
    Rubyと同じくALGOL系の文法を持つScalaは、関
    数型言語のエッセンスを全て備えながら、Rubyと
    同じく徹底したオブジェクト指向言語でもある。
    Scalaこそが、Ruby使いが関数型プログラミングを
    学ぶのに最も適した言語と言えよう。
    Scalaを学べば、きっとよりよいRuby使いになれる
    はずである…たぶん。
    そこで
    そこでScala
    Scalaですよ
    ですよ

    View Slide

  6. まずはScala
    の文法の基礎
    から
    魔法少女Scalaちゃん ©2009 熊ジェット

    View Slide

  7. 1-1.
    1-1. 変数の定義
    変数の定義
    ■var(変数)型
    var 変数名:型=値
    例)
    > var n: Int = 1
    ☞n: Int = 1
    > n = 3
    ☞n: Int = 3
    ■val(値)型
    val 変数名:型=値
    例)
    > val n: Int = 1
    ☞n: Int = 1
    > n = 3
    ☞error:
    reassginment to val
    再代入できない!
    ≪Scalaちゃん推奨≫
    ≪使ったらある意味負け≫

    View Slide

  8. > val n: Int = 1
    ☞n: Int = 1
    1-2.
    1-2. 代表的な型
    代表的な型
    > val str: String = ”hoge”
    ☞str: java.lang.String = hoge
    数値
    文字列
    > val sym: Symbol = 'piyo
    ☞sym: Symbol = 'piyo
    シンボル
    > val l: List[Int] = List(1,2,3)
    ☞l: List[Int] = List(1,2,3)
    リスト

    View Slide

  9. def 関数名(引数名:型, …):返り値の型 = {
    処理内容
    }
    例)
    > def max(x: Int, y: Int): Int = {
    | if (x < y) y else x
    | }
    > max(8, 3)
    ☞res1: Int = 8
    1-3.
    1-3. 関数の定義
    関数の定義

    View Slide

  10. 変数や関数の返り値の型宣言は、コンパイラ
    が推測できる限りにおいて省略
    省略できる!
    1-4.
    1-4. 型推論
    型推論
    例)
    > val i = 4
    ☞i: Int = 4
    > val d = List(0.1, 1.2, 3.4)
    ☞d: List[Double] = List(0.1, 1.2, 3.4)
    > def hello = ”Hello, World!”
    ☞hello: java.lang.String

    View Slide

  11. 1-5.
    1-5. 制御構文
    制御構文(1) - if
    (1) - if
    if (条件文1) 値1 else if (条件文2) 値2 …
    else 値3
    例)
    > if (str.size < 3) {
    | ”It's short.”
    | } else if (str.size < 6) {
    | ”Not so long.”
    | } else ”It's long.”
    ☞res1: java.lang.String = It's long.
    必ず値を返すことに注意!

    View Slide

  12. 1-6.
    1-6. 制御構文
    制御構文(2) - for
    (2) - for
    for (ブロック引数 for (ブロック引数 例)
    > for (i ☞1 2 3 4 5 6 7 8 9
    > for (i ☞res1: List[Int] = List(2,3,4,5,6,7,8,9,10)
    > for (i "," + j + "]")
    ☞[1,1][1,2][1,3][2,1][2,2][2,3]
    外2回、内3回の
    二重ループ

    View Slide

  13. 関数型プログラ
    ミングいくよー
    魔法少女Scalaちゃん ©2009 熊ジェット

    View Slide

  14. 2-1.
    2-1. 高階関数
    高階関数
    例)
    > List(1,2,3).map(n => n + 1)
    ☞res1: List[Int] = List(2,3,4)
    > List(1,2,3,4,5).filter(n => n % 2 == 0)
    ☞res2: List[Int] = List(2, 4)
    > List(1,2,3,4).map(_ * 2)
    ☞res3: List[Int] = List(2,4,6,8)
    Rubyのmapやsortメソッドのように、関数を引数に
    とる関数のこと。
    魔法の「_」(アンダーバー)

    View Slide

  15. 2-2.
    2-2. クロージャ
    クロージャ
    (引数:型,…) => 値
    例)
    > val sq = (n: Int) => Math.pow(n, 2).toInt
    > sq(6)
    ☞res1: Int = 36
    > List(1,2,3,4,5).map(sq)
    ☞res2: List[Int] = List(1,4,9,16,25)
    名前を定義せずに作成した関数のこと。「無名関
    無名関

    数」とも言う。変数に代入可。
    定義したクロージャ
    を変数sqに代入

    View Slide

  16. 2-3.
    2-3. 関数と変数は等価
    関数と変数は等価
    例)
    > val half = (n: Int) => n / 2
    ☞half: (Int) => Int =
    > half(14)
    ☞res1: Int => 7
    > def quartize(n: Int) = n / 4
    > val quarter = quartize _
    > quarter(20)
    ☞res1: Int => 5
    仮引数を「_」で表記
    (_)のカッコは省略可

    View Slide

  17. 2-4.
    2-4. パターンマッチング
    パターンマッチング(1)
    (1)
    引数 match {
    case パターン1 => 処理1 or 値1
    :
    case _ => 処理x or 値x
    }
    例)
    > val str = ”world”
    > str match {
    | case ”world” => println(”Hello!”)
    | case _ => ()
    | }
    ☞Hello! その他のケースは「_」にマッチ

    View Slide

  18. 2-5.
    2-5. パターンマッチング
    パターンマッチング(2)
    (2)
    例)
    > List(1,2,3) match {
    | case List(a, b, c) => a + b + c
    | case _ => 0
    }
    ☞res1: Int = 6
    > val v: Any = ”hoge”
    > v match {
    | case i: Int => i * 100
    | case s: String => s.size
    | }
    ☞res2: Int = 4
    変数a,b,cに値を束縛
    型のマッチ

    View Slide

  19. 2-6.
    2-6. 再帰関数
    再帰関数
    例)
    > def sumLoop(n: Int) = {
    | var total = 0
    | for (i | total
    | }
    > def sumRecursive(n: Int): Int = n match {
    | case 1 => 1
    | case _ => n + sumRecursive(n - 1)
    | }
    > (sumLoop(10), sumRecursive(10))
    ☞res1: (Int, Int) = (55,55)
    ループ型
    再帰型
    返り値の型宣言
    が必要!

    View Slide

  20. 2-7.
    2-7. カリー化
    カリー化
    例)
    > def multi(n: Int)(m: Int) = m * n
    > multi(6)(9)
    ☞res1: Int = 54
    > def multiTwo = multi(2)_
    > multiTwo(5)
    ☞res2: Int = 10
    複数の引数をとる関数を、引数が「元の関数の最初
    の引数」で返り値が「元の関数の残りの引数をとり結
    果を返す関数」であるような関数にすること。
    引数nに2を代入
    mはそのまま仮引数
    として渡す

    View Slide

  21. 2-8.
    2-8. 遅延評価
    遅延評価
    例)
    > class SchrodingerCat {
    | lazy val status = {
    | println("Here open a box..."); "Alive!"
    | }
    | }
    > val cat = new SchrodingerCat
    > cat.status
    ☞Here open a box...
    ☞res1: java.lang.String = Alive!
    オブジェクトのフィールドの評価を、初期化時ではなく
    参照時に行うようにする。
    まだstatusが評価されてない
    ここで初めてstatusが評価される!

    View Slide

  22. せめて、
    せめて、Ruby
    Ruby






    魔法少女Scalaちゃん ©2009 熊ジェット

    第参最終章

    View Slide

  23. 3-1. Implicit Conversion
    3-1. Implicit Conversion
    例)
    > class Cat
    > class Man { def greet = ”Hello!” }
    > implicit def cat2man(c: Cat): Man = new Man
    > val cat = new Cat
    > cat.greet
    ☞res1: java.lang.String = Hello!
    Rubyはオープンクラスなので既存のクラスを自由に上書
    きできる。しかしScalaは厳密な静的型付け言語のため同
    じことはできない。しかし暗黙の型変換
    暗黙の型変換を使えば、おおよ
    その場合その目的を達成できる。
    瞬間的にCatオブジェクトが
    Manオブジェクトに変身!

    View Slide

  24. 3-2. Structural Subtyping
    3-2. Structural Subtyping
    例)
    > class Cat
    > class Duck {
    | def swim = ()
    | def quack = "Quaaa!"
    | }
    > def duckTest[T](x: T { def swim; def quack:
    String }) = "You're a duck!"
    > duckTest(new Duck)
    ☞res1: java.lang.String = You're a duck!
    > duckTest(new Cat)
    ☞: error: type mismatch
    Scalaでダックタイピング
    ダックタイピングっぽいことをやるための仕組み。
    Tはswimメソッドとquack
    メソッドをもった型クラス

    View Slide

  25. 以上です。
    もっとScalaを詳しく
    知りたくなった人は、
    コップ本買ってね。
    魔法少女Scalaちゃん ©2009 熊ジェット
    『Scalaスケーラブルプログラミング』
    (通称:コップ本)

    View Slide