2013年2月9日土曜日

scheme(R5RS)のapplyの仕様

schemeのapplyは手続きとリストの二つの引数をとるのだと思っていました。 (「計算機プログラムの構造と解釈」の107ページの注にもそう書いてあります。)

なので、
(map (lambda (x y) (+ x y)) '(1 2) '(3 4)) ==> (4 6)
というようなことをしたいときに、'((1 2) (3 4))を関数に渡すには、
(apply map (cons (lambda (x y) (+ x y)) '((1 2) (3 4))))
と形式上リストにして渡す必要があると思っていました。

しかし、
(apply map (lambda (x y) (+ x y)) '((1 2) (3 4)))
でも正しく動きます。

R5RS(http://www.schemers.org/Documents/Standards/R5RS/)を確認すると、 以下の様になっていました。

(apply proc arg1 . . . args)
proc は手続きでなければならず,args はリストでなければならない。proc を,リスト (append (list arg1 . . . ) args) の各要素を各実引数として呼び出す。
(apply + (list 3 4)) ==> 7
(define compose
  (lambda (f g)
    (lambda args
      (f (apply g args)))))
((compose sqrt *) 12 75) ==> 30
(Suzuki Hisao さんの日本語訳より引用 (http://www.unixuser.org/~euske/doc/r5rs-ja/))

argsは最後だけ特別扱いなのですね。 基本の関数としてはちょっと複雑ですけれど、 「手続きとリストの二つの引数をとる」と思ってても別に困らないのは、 さすがschemeです。