C、C ++、Java、Pythonなどの他の言語との類似点を描くために、コードが変更するのは、Lisperが使用する表現ではない場合でも、「ローカル変数」です(Lisp用語での表現はローカルの「バインディング」になります) )。
例のように関数パラメーターを使用するか、次のような標準形式を使用して、ローカル変数を作成できます。
(let ((x 12)) ...)
(do ((x 0 (1+ i))) ...)
(dotimes (x 10) ...)
(loop for x from 0 to 10 do ...)
一方、実装では、すべてのローカル変数がパラメーターを使用して作成され、他の形式は単にそれに拡張されたマクロである可能性があります。例えば:
(let ((x 10)) ...)
と同等です
(funcall (lambda (x) ...) 10)
また、実際にコードフラグメントを読み取ると、x
特別に宣言されている可能性があるため、ある意味で「グローバル変数」である可能性があることにも注意してください。
(defvar x 12)
;; ==> x
(defun bar ()
(format t "The value of x is ~a" x))
;; ==> bar
(defun foo (x)
(bar))
;; ==> foo
(foo 42)
The value of x is 42
;; ==> NIL
x
;; ==> 12
変数を「特別な」と宣言すると、(defvar ...)
それを使用して処理が異なります。つまり、パラメーターとして使用するか、フォームで使用するたびに(let ..)
、コードが実行するのは、現在の値を保存し、新しく提供された値を使用してからです。関数またはを終了した後に値を復元しますlet
。
したがって、これらの変数は両方とも「グローバル」(外部関数がそれらを見ることができるため)であると同時にローカル(関数またはletの終了後に前の値が復元されるため)でもあります。
標準的な規則では、特別な変数に「イヤーマフ」という名前を付けます。つまり、名前の最初と最後の両方にアスタリスクを付けます。
(defvar *x* 12)
これは、誰があなたのコードを読んで、変数が特別であることを理解するのに役立ちます。ただし、これは言語によって義務付けられておらず、特別な変数には任意の名前を使用できることに注意してください。
C、C ++、Java、Pythonの特別な変数に似たものはありません。
setq
とについての最後の注意setf
。Lispの低レベルを理解して、なぜ必要なのかを理解する必要があるため、ここでは少し注意setq
が必要です。Common Lispを使用している場合は、単に忘れてsetq
、常にを使用する必要がありますsetf
。
setf
は、必要なときに拡張されるマクロsetq
です(ただし、必要なときにsetq
変更することもできsetf
ます(シンボルマクロ)。これは、初心者にとって混乱を招く可能性がある場所です)。
最後の例は「クロージャ」の場合です。関数(フォームで名前が付けられているかどうかに関係なく(lambda ...)
)を定義すると、関数は表示されている変数を「キャプチャ」して後で使用できます。よく見られるより単純なケースは「加算器」です。
(defun adder (x)
(lambda (y) (incf x y)))
この関数は、渡された値を内部トータライザーに追加し続ける関数を返します。
(let ((f (adder 10)))
(print (funcall f 3))
(print (funcall f 9))
(print (funcall f 11)))
出力は13(10 + 3)、22(13 + 9)、33(22 + 11)になります。
匿名関数はローカル変数を「キャプチャ」しx
、関数を終了した後でも使用できますadder
。C、C ++、Javaなどの言語では、変数を定義したスコープを終了すると、ローカル変数は存続できません。
C ++ 11には無名関数がありますが、それでも変数をキャプチャしてスコープを存続させることはできません(無名関数のローカル変数にコピーすることはできますが、これは同じではありません)。