akimachoのはてなブログ

ICTとデザインのためのブログ

『プログラミングの基礎』読書日誌-17日目-

はじめに

今回は,第17章 高階関数を使ったリスト処理です.前回のmapに加えて,filter,局所関数定義,名前のない関数(匿名関数)などが紹介されています.

filter

関数filterは,条件を満たす要素を取り出す関数です.次のようになります.

let rec filter p lst = match lst with
    [] -> []
    | first :: rest -> 
            if (p first)
            then first :: (filter p rest)
            else (filter p rest)

fold_right

関数fold_rightは,各要素をまとめあげる関数です.次のようになります.

(* 目的 : initからはじめてlstの要素を右から順にfを施し込む *)
(* fold_right : ('a -> 'b -> 'b) -> 'a list -> 'b -> 'b *)
let rec fold_right f lst init = match lst with
    [] -> init
    | first :: rest ->
            (f first (fold_right f rest init))

局所関数定義

他では使わないとわかっている関数は,局所関数定義を用いて局所的に宣言します.

let 関数名 引数 ... =in

例p.143

(* 目的 : 受け取ったリストlstの各要素の和を求める  *)
(* sum : int list -> int *)
let sum lst =
    (* 目的 : first と rest_resultを加える *)
    (* add_int : int -> int -> int *)
    let add_int first rest_result = first + rest_result in
        List.fold_right add_int lst 0

名前のない関数

名前のない関数はその名の通り名前を持たない関数で,関数リテラル,匿名関数や無名関数,ラムダ式とも呼ばます(実際にはそれぞれ違いがあるようです).Ocamlでは次のように書きます.

無名関数 - Wikipedia

fun 引数 ... ->

名前のない関数を使うことで,一度しか使わない関数に名前を与える手間を省くことができます.しかし,名前のない関数では再帰関数を定義することはできないことに注意が必要です.

また,今まで私たちは関数定義に以下のような書き方を使ってきました.

let 関数名 引数 ... =

上の文は,実は下の文のシンタックスシュガー(糖衣構文)だったようです.

>|ocaml
let 変数名 = fun 引数 ... -> 式
|

知らぬ間に,名前のない関数を使っていたわけですね.

infix関数とprefix関数

prefix関数とは,関数を先頭に引数をその後に並べて呼び出すような関数のことを指します.通常の関数がその例です.一方,infix関数とは,関数を先頭に引数をその後ろに並べて呼び出すような関数を指します.演算子がその例です.ちなみにprefixは接頭辞,infixとは接中辞という意味です.

OCamlでは,カッコでくくることによりinfix関数をprefix関数にすることができます.それにより高階関数に引数として渡すことができるようになるわけです.

プログラミングの基礎 (Computer Science Library)

プログラミングの基礎 (Computer Science Library)