SlideShare a Scribd company logo
命令プログラミングから
関数プログラミングへ
 関数プログラマは問題をどう考えるか

  Scala 関西ビギナーズ 第 2 回
前提



• 厳密な正確性よりもわかりやすさを重視
関数プログラミングの関数
数学でいうところの関数
f(x) = x + 1
だから Scala では
•関数定義に = (イコール) を使用
•関数内で最後に評価された値が返る
         def f(x: Int) {x + 1}
Which
is      def f(x: Int) = return x + 1
better?
        def f(x: Int) = x + 1
                        ※注: 上の 2つは正しいコードではありません。
関数プログラミング (狭義)

• 変更可能な変数

• 再代入

• ループなどの命令型の制御

 を使わずにプログラミングすること
命令プログラマの疑問

 再代入やループなしにどうやって書くのか?

int sum = 0;
for (int i = 0; array.length = 0; i++) {
  sum += array[i];
}
return sum;
i = i + 1;

最初に見たとき違和感ありませんでしたか?
プログラミングの関心事
命令プログラミング

 具体的な手順を記述

関数プログラミング

 対象の性質を定義
関数プログラミングでの問題へのアプローチ




問題を抽象化・一般化
問題


ある自然数を引数にとり、0から当
該自然数までの整数の合計を返す関
数を定義せよ
命令プログラミング
• 0からnまでカウントアップ

• カウントアップした数字を足し込んでいく

int f(int n) {
    int total = 0;
    for (int i = 0; i <= n; i++) {
        total += i;
    }
    return total;
}
例示して性質を抽出
f(0) = 0
f(1) = 0 + 1
f(2) = 0 + 1 + 2
f(3) = 0 + 1 + 2 + 3
...
f(n) = 0 + 1 + 2 + 3 + ... + n
具体から抽象へ
f(0) = 0
f(1) = f(0) + 1
f(2) = f(1) + 2
f(3) = f(2) + 3
...
f(n) = f(n - 1) + n
f(0) = 0
f(n) = f(n - 1) + n



def f(n: Int): Int =
   if (n = 0) 0
   else f(n - 1) + n
問題


指定された自然数の階乗を返す関数
を定義せよ
階乗
f(0) = 1
f(1) = 1
f(2) = 2 * 1
f(3) = 3 * 2 * 1
...
f(n) = n * ... * 3 * 2 * 1
階乗 (一般化)
f(0) = 1
f(1) = 1 * f(0)
f(2) = 2 * f(1)
f(3) = 3 * f(2)
...
f(n) = n * f(n - 1)
f(0) = 1
f(n) = n * f(n - 1)



def f(n: Int): Int =
   if (n = 0) 1
   else n * f(n - 1)
指定された数までのフィボナッチ数
列を返す関数の定義は?
問題


指定されたリスト内の数の合計を返
す関数 sum を定義せよ
リストの定義
• 空リスト Nil はリスト
• head が要素、tail がリストなら
head :: tail もリスト



自身を使って定義されたデータ型
•再帰的なデータ型
•自己参照をするデータ型
例示
1 :: 5 :: 1 :: 2 :: 8 :: Nil
:: は右結合なので

1 :: (5 :: (1 :: (2 :: (8 :: Nil))))
1 :: (5 :: 1 :: 2 :: 8 :: Nil)
     5 :: (1 :: 2 :: 8 :: Nil)
          1 :: (2 :: 8 :: Nil)
               2 :: (8 :: Nil)
                     8 :: Nil
一般化
sum(1 :: 5 :: 1 :: 2 :: 8 :: Nil)
1 + sum(5 :: 1 :: 2 :: 8 :: Nil)
     5 + sum(1 :: 2 :: 8 :: Nil)
          1 + sum(2 :: 8 :: Nil)
               2 + sum(8 :: Nil)
                     8 + sum(Nil)
sum(Nil) = 0
head + sum(tail)
sum(Nil) = 0
head + sum(tail)


def sum(list: List[Int]): Int =
    if (list.isEmpty) 0
    else list.head + sum(list.tail)

def sum(list: List[Int]): Int = list match {
    case Nil => 0
    case head :: tail => head + sum(tail)
}
型にあわせて処理を行う

型が処理を導くという側面も
末尾再帰や木構造の処理、Option や
例外処理のことなど他にもたくさん
話したいことはあるのですが…。
お薦め書籍
  Scala ではなく OCaml だが
  関数プログラミングの基礎
  が身につけられる



  プログラミングの基礎
  浅井健一
  サイエンス社
木虎 直樹
@kitora_naoki

テキストマイニング
プログラミング
 Scala, Java, JavaScript, Python, OCaml
インフラ
 network, Web, AP, RDBMS, MTA, DNS, etc.

More Related Content

命令プログラミングから関数プログラミングへ