練習問題 3.11 (2)

本文中で与えられた再帰的な定義で n個の中からm個を選ぶ場合の数 ¥left(¥begin{array}n¥¥m¥end{array}¥right) を求める関数 comb を定義せよ,という問題。再帰的な定義は本文(p.51)をみること(書くのが面倒なので)。

# let rec comb n m =
if m = 0 then 1
else if n = m then 1
else comb (n-1) m + comb (n-1) (m-1)
;;
val comb : int -> int -> int = <fun>
# comb 5 3;;
# comb 2 1;;
- : int = 2

練習問題 3.11 (3)

末尾再帰的関数を使ってフィボナッチ数を計算する iterfib

# let iterfib n =
let rec fibn (x, y) i =
if i = n then y
else fibn (y, x + y) (i+1)
in
fibn (0, 1) 1
;;
val iterfib : int -> int = <fun>
# iterfib 1;;
- : int = 1
# iterfib 2;;
- : int = 1
# iterfib 3;;
- : int = 2
# iterfib 4;;
- : int = 3
# iterfib 5;;
- : int = 5
# iterfib 6;;
- : int = 8

ちゃんと末尾再起になってるよね?

条件分岐

else は省略できない。

# let even n = if n mod 2 = 0 then true else false;;
val even : int -> bool = <fun>
# even 3;;
- : bool = false
# even 8;;
- : bool = true

ところで mod が中置演算子なのはへんな気分だ。

# 9 mod 3;;
- : int = 0
# (mod) 9 2;;
- : int = 1

再帰的な関数

再帰的な関数と定義するには rec をつける。

# let rec fact n = if n = 0 then 1 else n * fact (n - 1);;
val fact : int -> int = <fun>
# fact 3;;
- : int = 6
# fact 6;;
- : int = 720

あまり大きな整数は表現できないらしい。

# fact 30;;
- : int = -738197504

ユークリッドの互除法で最大公約数

プログラミング in OCaml ~関数型プログラミングの基礎からGUI構築まで~ p.51より。再帰的に定義する。

# let rec euclid m n =
if m = n then m
else if m > n then euclid n m
else euclid (n - m) m
;;
val euclid : int -> int -> int = <fun>
# euclid 12 60;;
- : int = 12
# euclid 12 6;;
- : int = 6

基本的には m≦n のつもりで書いているけど,n – m と m の大小関係は決定できないので3行目を入れた。これで m と n の大小関係も気にしなくて済んでいる。

相互再帰

2つ(あるいはそれ以上)の関数を and でつないでいっぺんに定義できるがおもしろい。

and の後の関数には let rec が要らない。

# let rec even n =
if n = 0 then true else odd (n - 1)
and odd n =
if n = 0 then false else even (n - 1)
;;
val even : int -> bool = <fun>
val odd : int -> bool = <fun>
# even 3;;
- : bool = false
# even 4;;
- : bool = true
# odd 5;;
- : bool = true
# odd 8;;
- : bool = false

演算子

整数と実数で演算子が違う。

  • 整数: +, -, *, /
  • 実数: +., -., *., /.

間違えるとエラーになる。

# 1 + 2;;
- : int = 3
# 1.0 + 2.5;;
Characters 0-3:
1.0 + 2.5;;
^^^
This expression has type float but is here used with type int
# 1.0 +. 2.5;;
- : float = 3.5

文字列の連結

# "Hello," ^ " world.";;
- : string = "Hello, world."

文字列.[n] という書き方でn番目の文字を取得できる(先頭が0番目)。

# "Hello, world.".[0];;
- : char = 'H'
# "Hello, world.".[4];;
- : char = 'o'