狠狠撸

狠狠撸Share a Scribd company logo
搁耻产测使いのための



     Scalaで学ぶ
関数型プログラミング
      Presented by おおかゆか
自己绍介
       おおかゆか (id: oukayuka)
フリーランスのWebプログラマ。
元々はPHPerでしたが、最近はもっぱらRails案件を
生業に活動中。
Scalaに手を出したのは、ほんの3ヶ月ほど前。
エンジニアがお金について考えるためのrake:money
という勉強会を主宰してます。月1の頻度で都内にて
開催しているので、興味があればどうぞ。
  http://groups.google.co.jp/group/rakemoney
?注意?
Scalaって何?という方は、これを読
む前にまず
    「搁耻产测使いのための
      Scalaのススメ」
をご一読ください。
?http://ja.verbmode.net/2009/10/03/
  recommend_of_scala_for_rubyist
よいRuby使いになるために
Rubyは「acceptable Lisp」とか「MatzLisp」と
揶揄されることもあるくらい、Lispからの影響
が強い言語である。
Ruby使いがより一歩ステップアップするため
にLispを学ぼうとはよく言われるところ。
Eric Raymond も Paul Grahamも、ことあるご
とにLispを薦めてくる。
しかしMatzも認めるように、Lispは普通の人
には扱いきれない習得コストの高い言語。
そこでScalaですよ
それでもScalaなら…、Scalaならきっと何とかしてく
れる。というのも、Scalaは最もRubyに似た関数型
言語だから。
Rubyと同じくALGOL系の文法を持つScalaは、関
数型言語のエッセンスを全て備えながら、Rubyと
同じく徹底したオブジェクト指向言語でもある。
Scalaこそが、Ruby使いが関数型プログラミングを
学ぶのに最も適した言語と言えよう。
Scalaを学べば、きっとよりよいRuby使いになれる
はずである…たぶん。
? まずはScala
    の文法の基礎
    から

  魔法少女Scalaちゃん ?2009 熊ジェット
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
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)
1-3. 関数の定義
def 関数名(引数名:型, …):返り値の型 = {
   処理内容
}

例)
> def max(x: Int, y: Int): Int = {
|    if (x < y) y else x
| }
> max(8, 3)
?res1: Int = 8
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) - 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. 制御構文(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 + "]")                    外2回、内3回の
?[1,1][1,2][1,3][2,1][2,2][2,3] 二重ループ
?
      関数型プログラ
      ミングいくよー


    魔法少女Scalaちゃん ?2009 熊ジェット
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)
2-2. クロージャ
名前を定義せずに作成した関数のこと。「無名関
数」とも言う。変数に代入可。
(引数:型,…) => 値

例)
> val sq = (n: Int) => Math.pow(n, 2).toInt
> sq(6)           定義したクロージャ
?res1: Int = 36 を変数sqに代入

> List(1,2,3,4,5).map(sq)
?res2: List[Int] = List(1,4,9,16,25)
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. パターンマッチング(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)
例)
> List(1,2,3) match {
|   case List(a, b, c) => a + b + c
|   case _ => 0
}                     変数a,b,cに値を束縛
?res1: Int = 6

> val v: Any = ”hoge” 型のマッチ
> v match {
|   case i: Int    => i * 100
|   case s: String => s.size
| }
?res2: Int = 4
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. カリー化
複数の引数をとる関数を、引数が「元の関数の最初
の引数」で返り値が「元の関数の残りの引数をとり結
果を返す関数」であるような関数にすること。
例)
> def multi(n: Int)(m: Int) = m * n
> multi(6)(9)
?res1: Int = 54

> def multiTwo = multi(2)_
> multiTwo(5)                引数nに2を代入
                             mはそのまま仮引数
?res2: Int = 10              として渡す
2-8. 遅延評価
オブジェクトのフィールドの評価を、初期化時ではなく
参照時に行うようにする。
例)
> class SchrodingerCat {
|   lazy val status = {
|     println("Here open a box..."); "Alive!"
|   }
| }    まだstatusが評価されてない

> val cat = new SchrodingerCat
> cat.status              ここで初めてstatusが評価される!
?Here open a box...
?res1: java.lang.String = Alive!
?        せめて、Ruby
                っ
               ぽ
         第参最終章
                く

    魔法少女Scalaちゃん ?2009 熊ジェット
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オブジェクトが
                    Manオブジェクトに変身!
> cat.greet
?res1: java.lang.String = Hello!
3-2. Structural Subtyping
Scalaでダックタイピングっぽいことをやるための仕組み。
      ダックタイピング
例)
> class   Cat
> class   Duck {
| def     swim = ()
| def     quack = "Quaaa!"      Tはswimメソッドとquack
| }                             メソッドをもった型クラス


> 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を詳しく
   知りたくなった人は、
   コップ本買ってね。
      『Scalaスケーラブルプログラミング』
      (通称:コップ本)



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

More Related Content

(搁耻产测使いのための)厂肠补濒补で学ぶ関数型プログラミング