引数のリストに手続きを適用する


Tags: R6RS, 手続き

引数のリストに手続きを適用するには apply 手続きを使う。

(import (rnrs))

(apply + '(1 2 3 4)) ; => 10

(apply list 'a 'b '(c d e)) ; => (a b c d e) 

可変長引数を取る手続きを呼び出す場合、省略可能な部分をリストに保存しておいて適用できると便利なことがある。例えば、指定の *load-path* からファイルを探して開く open-file-input-port/load-path 手続きを考える。この手続きはファイルを *load-path* 内から探索する以外は open-file-input-port 手続きと同一の引数を取るものとする。 apply のない場合には case-lambda で場合分けをして引数を渡すか、残余引数を carcdr で分解しなければならない。 apply を使うと次のように書ける。

(import (rnrs) (srfi :2) (srfi :39))

(define *load-path*
  (make-parameter '("/usr/share/scheme/" "/usr/local/share/scheme/")))

(define (open-file-input-port/load-path fn . opts)
  (or (exists (lambda (path)
                (and-let* ((p (string-append path fn))
                           ((file-exists? p)))
                  (apply open-file-input-port p opts)))
              (*load-path*))
      (raise
       (condition
        (make-who-condition 'open-file-input-port/load-path)
        (make-message-condition "file does not exist in load path")
        (make-irritants-condition (*load-path*))
        (make-i/o-file-does-not-exist-error fn)))))