Upload
ouka-yuka
View
16.541
Download
2
Embed Size (px)
DESCRIPTION
主にRuby使いを対象とした、Scalaによる関数型プログラミング入門です。
Citation preview
ScalaScalaで学ぶで学ぶ関数型プログラミング関数型プログラミング
Ruby使いのための
Presented by おおかゆか
自己紹介自己紹介
おおかゆか (おおかゆか (id: oukayukaid: oukayuka))
フリーランスのWebプログラマ。
元々はPHPerでしたが、最近はもっぱらRails案件を
生業に活動中。
Scalaに手を出したのは、ほんの3ヶ月ほど前。
エンジニアがお金について考えるためのrake:money rake:money
という勉強会を主宰してます。月1の頻度で都内にて
開催しているので、興味があればどうぞ。
http://groups.google.co.jp/group/rakemoney
Scalaって何?という方は、これを読む前にまず
「Ruby使いのための
Scalaのススメ」
をご一読ください。
☞http://ja.verbmode.net/2009/10/03/ recommend_of_scala_for_rubyist
≪≪注意≫注意≫
Rubyは「acceptable Lisp」とか「MatzLisp」と揶揄されることもあるくらい、Lispからの影響が強い言語である。
Ruby使いがより一歩ステップアップするためにLispを学ぼうとはよく言われるところ。
Eric Raymond も Paul Grahamも、ことあるごとにLispを薦めてくる。
しかしMatzも認めるように、Lispは普通の人には扱いきれない習得コストの高い言語。
よいよいRubyRuby使いになるために使いになるために
それでもScalaなら…、Scalaならきっと何とかしてくれる。というのも、Scalaは最もRubyに似た関数型言語だから。
Rubyと同じくALGOL系の文法を持つScalaは、関数型言語のエッセンスを全て備えながら、Rubyと同じく徹底したオブジェクト指向言語でもある。
Scalaこそが、Ruby使いが関数型プログラミングを学ぶのに最も適した言語と言えよう。
Scalaを学べば、きっとよりよいRuby使いになれるはずである…たぶん。
そこでそこでScalaScalaですよですよ
まずはScalaの文法の基礎から
魔法少女Scalaちゃん ©2009 熊ジェット
➀
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ちゃん推奨≫≪使ったらある意味負け≫
> 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)
リスト
def 関数名(引数名:型, …):返り値の型 = { 処理内容}
例)> def max(x: Int, y: Int): Int = {| if (x < y) y else x| }> max(8, 3)☞res1: Int = 8
1-3. 1-3. 関数の定義関数の定義
変数や関数の返り値の型宣言は、コンパイラ
が推測できる限りにおいて省略省略できる!
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
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.
必ず値を返すことに注意!
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回の二重ループ
関数型プログラミングいくよー
魔法少女Scalaちゃん ©2009 熊ジェット
➁
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メソッドのように、関数を引数に
とる関数のこと。
魔法の「_」(アンダーバー)
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に代入
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
仮引数を「_」で表記(_)のカッコは省略可
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! その他のケースは「_」にマッチ
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に値を束縛
型のマッチ
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)
ループ型
再帰型
返り値の型宣言が必要!
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はそのまま仮引数として渡す
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が評価される!
せめて、せめて、RubyRubyっっぽぽくく
魔法少女Scalaちゃん ©2009 熊ジェット
➌
第参最終章
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オブジェクトに変身!
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メソッドをもった型クラス
以上です。
もっとScalaを詳しく知りたくなった人は、コップ本買ってね。
魔法少女Scalaちゃん ©2009 熊ジェット
『Scalaスケーラブルプログラミング』(通称:コップ本)