引数を一部固定した手続きを作る


Tags: R6RS, 手続き, SRFI

高階関数に手続きを渡す場合、既存の手続きの引数を一部固定しただけの手続きが必要になることがしばしばある。例えば、リストの各要素に 1 を足す計算を考える。標準では

(import (rnrs))

(map (lambda (x) (+ x 1)) '(1 2 3 4 5)) ; => (2 3 4 5 6)

と書く。また、各要素を 2 倍する計算、各要素から 1 を引く計算など、これに類似したパターンは多い。

このような場合、 SRFI-26 を使うと簡潔に書けることがある。

(import (rnrs) (srfi :26))

(map (cut + <> 1) '(1 2 3 4 5)) ; => (2 3 4 5 6)
(map (cut * 2 <>) '(1 2 3 4 5)) ; => (2 4 6 8 10)
(map (cut - <> 1) '(1 2 3 4 5)) ; =>(0 1 2 3 4)

cut マクロは <> で指定された部分に引数を取る lambda 式に変換される。 <> は複数指定することもできる。

(import (rnrs) (srfi :26))

(map (cut <= <> 5 <>) '(2 4 0 8) '(5 2 9 1)) ; => (#t #f #t #f)

ただし、引数の順序を交換するようなことはできないので、その場合には lambda 式を書かなければならない。

(import (rnrs))

(map (lambda (x y) (cons y x)) '(1 3 5 7) '(2 4 6 8)) ; => ((2 . 1) (4 . 3) (6 . 5) (8 . 7))

引数を取らない手続きを thunk と呼ぶ。 <> のない cut を使うと thunk を短かく書けることがある。

(call-with-values (cut f a b) g) ; === (call-with-values (lambda () (f a b)) g)