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

17,194 views

Published on

主にRuby使いを対象とした、Scalaによる関数型プログラミング入門です。

Published in: Technology, Education
0 Comments
24 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
17,194
On SlideShare
0
From Embeds
0
Number of Embeds
3,360
Actions
Shares
0
Downloads
48
Comments
0
Likes
24
Embeds 0
No embeds

No notes for slide

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

  1. 1. Ruby使いのための Scalaで学ぶ 関数型プログラミング Presented by おおかゆか
  2. 2. 自己紹介 おおかゆか (id: oukayuka) フリーランスのWebプログラマ。 元々はPHPerでしたが、最近はもっぱらRails案件を 生業に活動中。 Scalaに手を出したのは、ほんの3ヶ月ほど前。 エンジニアがお金について考えるためのrake:money という勉強会を主宰してます。月1の頻度で都内にて 開催しているので、興味があればどうぞ。 http://groups.google.co.jp/group/rakemoney
  3. 3. ≪注意≫ Scalaって何?という方は、これを読 む前にまず 「Ruby使いのための Scalaのススメ」 をご一読ください。 ☞http://ja.verbmode.net/2009/10/03/   recommend_of_scala_for_rubyist
  4. 4. よいRuby使いになるために Rubyは「acceptable Lisp」とか「MatzLisp」と 揶揄されることもあるくらい、Lispからの影響 が強い言語である。 Ruby使いがより一歩ステップアップするため にLispを学ぶべきとはよく言われるところ。 Eric Raymond も Paul Grahamも、ことあるご とにLispを薦めてくる。 しかしMatzも認めるように、Lispは普通の人 には扱いきれない習得コストの高い言語。
  5. 5. そこでScalaですよ それでもScalaなら…、Scalaならきっと何とかしてく れる。というのも、Scalaは最もRubyに似た関数型 言語だから。 Rubyと同じくALGOL系の文法を持つScalaは、関 数型言語のエッセンスを全て備えながら、Rubyと 同じく徹底したオブジェクト指向言語でもある。 Scalaこそが、Ruby使いが関数型プログラミングを 学ぶのに最も適した言語と言える。 Scalaを学べば、きっとよりよいRuby使いになれる はず…たぶん。
  6. 6. ➀ まずはScala の文法の基礎 から 魔法少女Scalaちゃん ©2009 熊ジェット
  7. 7. 1-1. 変数の定義 ≪使ったらある意味負け≫ ≪Scalaちゃん推奨≫ ■var(変数)型 ■val(値)型 var 変数名:型=値 val 変数名:型=値 例) 例) > var n: Int = 1 > val n: Int = 1 ☞n: Int = 1 ☞n: Int = 1 再代入できない! > n = 3 > n = 3 ☞n: Int = 3 ☞error: reassginment to val
  8. 8. 1-2. 代表的な型 数値 > val n: Int = 1 ☞n: Int = 1 文字列 > 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)
  9. 9. 1-3. 関数の定義 def 関数名(引数名:型, …):返り値の型 = { 処理内容 } 例) > def max(x: Int, y: Int): Int = { | if (x < y) y else x | } > max(8, 3) ☞res1: Int = 8
  10. 10. 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
  11. 11. 1-5. 制御構文(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.
  12. 12. 1-6. 制御構文(2) - for for (ブロック引数 <- コレクション; …) 処理内容 for (ブロック引数 <- コレクション; …) yield 値 例) > for (i <- 1 to 9) print(i + ” ”) ☞1 2 3 4 5 6 7 8 9 > for (i <- (1 to 9).toList) yield i + 1 ☞res1: List[Int] = List(2,3,4,5,6,7,8,9,10) > for (i <- 1 to 2; j <- 1 to 3) print("[" + i + "," + j + "]") ☞[1,1][1,2][1,3][2,1][2,2][2,3]
  13. 13. ➁ 関数型プログラ ミングいくよー 魔法少女Scalaちゃん ©2009 熊ジェット
  14. 14. 2-1. 高階関数 Rubyのmapやsortメソッドのように、関数を引数に とる関数のこと。 例) > 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)
  15. 15. 2-2. クロージャ Rubyのmapやsortメソッドのように、関数を引数に とる関数のこと。「無名関数」とも言う。 無名関数 (引数:型,…) => 値 例) > 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)
  16. 16. 2-3. 関数と変数は等価 例) > val half = (n: Int) => n / 2 ☞half: (Int) => Int = <function> > half(14) ☞res1: Int => 7 > def quartize(n: Int) = n / 4 > val quarter = quartize _ > quarter(20) ☞res1: Int => 5
  17. 17. 2-4. パターンマッチング(1) 引数 match { case パターン1 => 処理1 or 値1 : case _ => 処理x or 値x } 例) > val str = ”world” > str match { | case ”world” => println(”Hello!”) | case _ => () | } ☞Hello!
  18. 18. 2-5. パターンマッチング(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
  19. 19. 2-6. 再帰関数 例) ループ型 > def sumLoop(n: Int) = { | var total = 0 | for (i <- 1 to n) total += 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)
  20. 20. 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
  21. 21. 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!
  22. 22. ➌ せめて、Ruby っ ぽ 第参最終章 く 魔法少女Scalaちゃん ©2009 熊ジェット
  23. 23. 3-1. Implicit Conversion Rubyはオープンクラスなので既存のクラスを自由に上書 きできる。しかしScalaは厳密な静的型付け言語のため同 じことはできない。しかし暗黙の型変換を使えば、その目 暗黙の型変換 的を達成できる場合が多い。 例) > 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!
  24. 24. 3-2. Structual Subtyping Scalaでダックタイピングっぽいことをやるための仕組み。 ダックタイピング 例) > 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!
  25. 25. 以上です。 もっとScalaを詳しく 知りたくなった人は、 コップ本買ってね。 『Scalaスケーラブルプログラミング』 (通称:コップ本) 魔法少女Scalaちゃん ©2009 熊ジェット

×