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

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

Embed Size (px)

DESCRIPTION

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

Citation preview

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

ScalaScalaで学ぶで学ぶ関数型プログラミング関数型プログラミング

Ruby使いのための

Presented by おおかゆか

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

自己紹介自己紹介

おおかゆか (おおかゆか (id: oukayukaid: oukayuka))

フリーランスのWebプログラマ。

元々はPHPerでしたが、最近はもっぱらRails案件を

生業に活動中。

Scalaに手を出したのは、ほんの3ヶ月ほど前。

エンジニアがお金について考えるためのrake:money rake:money

という勉強会を主宰してます。月1の頻度で都内にて

開催しているので、興味があればどうぞ。

http://groups.google.co.jp/group/rakemoney

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

Scalaって何?という方は、これを読む前にまず

「Ruby使いのための

Scalaのススメ」

をご一読ください。

☞http://ja.verbmode.net/2009/10/03/  recommend_of_scala_for_rubyist

≪≪注意≫注意≫

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

Rubyは「acceptable Lisp」とか「MatzLisp」と揶揄されることもあるくらい、Lispからの影響が強い言語である。

Ruby使いがより一歩ステップアップするためにLispを学ぼうとはよく言われるところ。

Eric Raymond も Paul Grahamも、ことあるごとにLispを薦めてくる。

しかしMatzも認めるように、Lispは普通の人には扱いきれない習得コストの高い言語。

よいよいRubyRuby使いになるために使いになるために

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

それでもScalaなら…、Scalaならきっと何とかしてくれる。というのも、Scalaは最もRubyに似た関数型言語だから。

Rubyと同じくALGOL系の文法を持つScalaは、関数型言語のエッセンスを全て備えながら、Rubyと同じく徹底したオブジェクト指向言語でもある。

Scalaこそが、Ruby使いが関数型プログラミングを学ぶのに最も適した言語と言えよう。

Scalaを学べば、きっとよりよいRuby使いになれるはずである…たぶん。

そこでそこでScalaScalaですよですよ

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

まずはScalaの文法の基礎から

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

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

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

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

> 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)

リスト

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

def 関数名(引数名:型, …):返り値の型 = { 処理内容}

例)> def max(x: Int, y: Int): Int = {| if (x < y) y else x| }> max(8, 3)☞res1: Int = 8

1-3. 1-3. 関数の定義関数の定義

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

変数や関数の返り値の型宣言は、コンパイラ

が推測できる限りにおいて省略省略できる!

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

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

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.

必ず値を返すことに注意!

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

1-6. 1-6. 制御構文制御構文(2) - for(2) - forfor (ブロック引数 <- コレクション; …) 処理内容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回の二重ループ

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

関数型プログラミングいくよー

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

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

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メソッドのように、関数を引数に

とる関数のこと。

魔法の「_」(アンダーバー)

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

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

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

2-3. 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

仮引数を「_」で表記(_)のカッコは省略可

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

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

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

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に値を束縛

型のマッチ

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

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)

ループ型

再帰型

返り値の型宣言が必要!

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

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

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

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

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

せめて、せめて、RubyRubyっっぽぽくく

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

第参最終章

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

3-1. Implicit Conversion3-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オブジェクトに変身!

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

3-2. Structural Subtyping3-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)☞<console>: error: type mismatch

Scalaでダックタイピングダックタイピングっぽいことをやるための仕組み。

Tはsw imメソッドとquackメソッドをもった型クラス

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

以上です。

もっとScalaを詳しく知りたくなった人は、コップ本買ってね。

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

『Scalaスケーラブルプログラミング』(通称:コップ本)