compose

scheme(Gauche)でプログラミングをしていて、ドット対を行儀の良いリストに変換したい場面があった。変換する関数をまず思いつく通りに考えて書くとこんな要領だと思う。

(define (dot-pair->proper-list x)(list (car x)(cdr x)))

これは充分に単純で、意味も一目瞭然だ。しかし、単純だからと言ってバリエーションが無いわけではない。
car部とcdr部を取り出して多値で返すcar+cdrという関数があることは知っていたので、これを使えないかと考えてみた。多値を扱うというとcall-with-valuesやreceiveがあるのだが、この場合では冗長すぎる。隠れた便利関数がないものかとマニュアルを見ていてcomposeが使えることを発見した。

(define dot-pair->proper-list (compose list car+cdr))

composeは多値を返す関数もちゃんと良いように処理してくれるように出来ている。composeの存在は知っていたのだけれど、多値を考慮しているとは思ってなくて、以下のような感じで理解していた。

(define ((compose . fs) knil)(fold (cut <> <>) knil fs))

実際の挙動は以下のようになる。(マニュアルから引用)

Function: compose f …
複数の手続きを結合します。引数は全て手続きでなければなりません。 2つの引数が渡された時、(compose f g)は次の式と等価です。

(lambda args (call-with-values (lambda () (apply g args)) f))

2つ以上の引数が渡された場合は、次のように結合されます。

(compose f g h ...)  (compose (compose f g) h ...)
http://www.shiro.dreamhost.com/scheme/gauche/man/?l=jp&p=compose

composeをナメてた。ごめんなさい。
Document ID: 3e973e2de77f52d7e50793f85c65b195