Slide 1

Slide 1 text

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

Slide 2

Slide 2 text

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

Slide 3

Slide 3 text

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

Slide 4

Slide 4 text

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

Slide 5

Slide 5 text

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

Slide 6

Slide 6 text

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

Slide 7

Slide 7 text

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ちゃん推奨≫ ≪使ったらある意味負け≫

Slide 8

Slide 8 text

> 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) リスト

Slide 9

Slide 9 text

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

Slide 10

Slide 10 text

変数や関数の返り値の型宣言は、コンパイラ が推測できる限りにおいて省略 省略できる! 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

Slide 11

Slide 11 text

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. 必ず値を返すことに注意!

Slide 12

Slide 12 text

1-6. 1-6. 制御構文 制御構文(2) - for (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] 外2回、内3回の 二重ループ

Slide 13

Slide 13 text

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

Slide 14

Slide 14 text

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メソッドのように、関数を引数に とる関数のこと。 魔法の「_」(アンダーバー)

Slide 15

Slide 15 text

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に代入

Slide 16

Slide 16 text

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 仮引数を「_」で表記 (_)のカッコは省略可

Slide 17

Slide 17 text

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! その他のケースは「_」にマッチ

Slide 18

Slide 18 text

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に値を束縛 型のマッチ

Slide 19

Slide 19 text

2-6. 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) ループ型 再帰型 返り値の型宣言 が必要!

Slide 20

Slide 20 text

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はそのまま仮引数 として渡す

Slide 21

Slide 21 text

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が評価される!

Slide 22

Slide 22 text

せめて、 せめて、Ruby Ruby っ っ ぽ ぽ く く 魔法少女Scalaちゃん ©2009 熊ジェット ➌ 第参最終章

Slide 23

Slide 23 text

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オブジェクトに変身!

Slide 24

Slide 24 text

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 メソッドをもった型クラス

Slide 25

Slide 25 text

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