* * *
* *"> *
* * *
Akihito Nagata's Page
|
|
簡単なパターンマッチングrakuda
MLの強力な機能のひとつにパターンマッチングがある。パターンマッチングにより条件に依存した関数を定義できる。

match式を使う

match式の構文は
match expr with
  patt 1 -> expr 1
| patt 2 -> expr 2
.....
| patt n -> expr n
この文の意味は expr の評価結果がpatt jとマッチするならばexp jを返す。

例。

フィボナッチ関数
# let rec fib n =
  match n with
  0 -> 1
  | 1 -> 1
  | k -> fib (k - 2) + fib (k - 1);;
val fib : int -> int = <fun>
# fib 6;;
- : int = 13
この例ではまず引数である6がnに入る。最初に6が1に0にマッチするか試され、その次に1とマッチするか試される。しかし、両方ともマッチせず次に変数kとマッチするか試される。変数kは何にでもマッチするのでkとマッチしkに6が束縛され、fib (k - 2) + fib (k - 1)が評価される。つまりパターンマッチングに変数を入れるとワイルドカードとして使える。マッチさせておいてあとで使わない場合には普通"_"を使う。("_"は代入はできるが評価はできない。)

functionを使う

パターンマッチングはfunctionでも使うことができる。 functionを使ってfibを定義してみると、
# let rec fib = function 
  0 -> 1
  | 1 -> 1
  | k -> fib (k - 2) + fib (k - 1);;
val fib : int -> int = <fun>
# fib 6;;
- : int = 13
また、マッチする条件を複数書くことができて、
# let rec fib = function 
  0 | 1 -> 1
  | k -> fib (k - 2) + fib (k - 1);;
val fib : int -> int = <fun>
# fib 6;;
- : int = 13
とも書ける。この場合、0または1にマッチしたら1を返すという意味になる。
またfunctiontと良く似たものにfunがあるが、
fun p1 p2 ... pn -> e
function p1 -> function p2 -> ... function pn -> e
と等価。

不完全なマッチング

次のプログラムは引数に文字を取り、それが大文字ならばtrueを返す。
# let is_uppercase = function
  'A' .. 'Z' -> true;;
Characters 19-46:
Warning: this pattern-matching is not exhaustive.
Here is an example of a value that is not matched:
'a'
val is_uppercase : char -> bool = <fun>
# is_uppercase 'C';;
- : bool = true
# is_uppercase 'd';;
Uncaught exception: Match_failure ("", 19, 46).
しかし、引数が大文字で無い場合が定義されていないのでwarningが出される(errorではない)。大文字を引数として適用すればちゃんと動くが、小文字を入れると例外(後述)が発生する。
プログラムを書いていて明らかに全ての場合を書く必要がないということがわかるときでも、全ての式にマッチするように書いた方が良い(多分)。上の式を訂正すると、
# let is_uppercase = function
  'A' .. 'Z' -> true
 | _ -> false;;
|
前のページはこちら