next up previous
Next: 4 関数閉包(closure) Up: ソフトウェア第三 講義資料 クロージャ,スコープ,遅延評価,オブジェクト,立体モデル Previous: 2 第一級身分

3 Funarg問題(Function Argument Problem)

Lispでは,関数をデータとして扱えるようになっていますが,関数をデータと して扱えるようにする場合には, Function Argument Problem(funarg問題)が おこる. ラムダ式で与えられた関数の実行中に自由変数(そのラムダ式の中ではバイン ドされていない変数)の取り扱いがはっきりとしないために問題となる. たとえば,引数としてラムダ式を渡す場合の例をあげておく.

(defun down-foo (x)
   (down-baa '(lambda () (+ x 1))))

(defun down-baa (f &aux (x 100))
   (funcall f))

(defun down-baa (f)
  ((lambda (x) (funcall f)) 100))

(defun down-foo (x)
   (down-baa (quote (lambda () (+ x 1)))))

(defun down-foo2 (x)
   (down-baa (function (lambda () (+ x 1)))))

(defun down-foo3 (x)
   (down-baa #'(lambda () (+ x 1))))
この関数で (down-foo 10)とした場合に何が返るべきかという問題である. down-fooから ラムダ式 (lambda () (1+ x)) で表される関数が down-baa へ の引数として渡され,down-baaの中でその渡された ラムダ式内の変数 x(=10) が down-fooで渡された x なのか,down-baa の 局所変数である x(=100) べ きなのかという問題である. また,関数がラムダ式を値として返す場合にも同じような問題が生じる.

(defun up-foo (x) '(lambda () (1+ x)))

(defun up-baa (x) (funcall (up-foo 100)))
として,(up-baa 10)と呼んだ場合に,11が返るべきか101が返るべきかという 問題である.引数として渡す場合を downward funarg,結果として返す場合を upward funargと呼ぶ場合もある. 関数をデータとして扱えるようにするためには,このfunarg問題を解く必要が ある.このfunarg問題を解決するために,Common Lispでは,関数データ として関数閉包(function closure) を明確に定義することでこのような問題が 起こらないようにしている.

generated through LaTeX2HTML. M.Inaba 平成18年5月7日