Lisp における関数オブジェクト
出典: フリー百科事典『ウィキペディア(Wikipedia)』 (2020/10/03 01:18 UTC 版)
「関数オブジェクト」の記事における「Lisp における関数オブジェクト」の解説
Lisp においても、関数は、文字列やベクトル・リスト・数値と同様に変数に入れたり関数から返したりできる第一級オブジェクトであり、第一級関数を扱うことができる言語である。 Lisp はその最初から (lambda ...) という特殊形式による関数リテラルをはじめとして、第一級関数を扱うことができる言語であったが、1960年代から1970年前後までの実装では、動的スコープのためクロージャにはなっておらず、funarg問題(en:Funarg problem)が認識されることとなった。Scheme で、静的スコープと無限エクステント(メモリ上のオブジェクトは参照されている限り生存し続ける)による解決が示され、Common Lisp をはじめとする現代的な Lisp の多くは静的スコープを採用しており、lambda 特殊形式ではクロージャが作られる。しかし Emacs Lisp のように動的スコープの Lisp もまだ広く残っている。 Scheme では変数と関数で名前空間が分かれておらず、変数名を関数名と同様に使ってプログラムを書くことができる。 (define (hello s) (print (format "hello, ~a" s)) )(hello "world")(let ((f hello)) (f "Scheme") ) これを実行すると、 hello, worldhello, Scheme のように出力される。 これに対し、伝統的な Lisp の多くや Common Lisp は変数と関数で名前空間が分かれている。同様のプログラムを Common Lisp で書いた例を示す。 (DEFUN HELLO (S) (PRINT (FORMAT NIL "hello, ~A" S)) )(HELLO "world")(LET ((F #'HELLO)) (FUNCALL F "Common Lisp") ) これを実行すると、 hello, worldhello, Common Lisp のように出力される。 Common Lisp では、名前に対して、変数としての値と、関数とが別々に結びつけられていて、文脈により(カッコ内の並びの先頭にあるか、そうでないかにより)どちらかがアクセスされる。F という変数に関数値を束縛する所では、通常の文脈において関数にアクセスするために #' を名前の前に付けている。一方、並びの先頭の位置に、この例では F と書いても、その名前の関数がないというエラーになる。Common Lisp では一般に、FUNCALL か APPLY 関数を使って呼び出す。 変数と関数の名前空間を分けるか同じにするか、という議論は、Lisp に限らず現代的なプログラミング言語の設計において話題になる。ML などの現代的な関数型言語では当然のように同じ名前空間である。スクリプティング言語では、Python や JavaScript は同じ名前空間としたが、Ruby ではローカル変数とメソッドで別の名前空間とした。Lisp では「Lisp-1 対 Lisp-2 の議論」などと呼ばれる(en:Common Lisp#The function namespace を参照)。
※この「Lisp における関数オブジェクト」の解説は、「関数オブジェクト」の解説の一部です。
「Lisp における関数オブジェクト」を含む「関数オブジェクト」の記事については、「関数オブジェクト」の概要を参照ください。
- Lisp における関数オブジェクトのページへのリンク