あなたの質問に直接答えるには、「使用されるたびnext
にリセットされません」0
count
(define count (let ((next 0))
(lambda ()
(let ((v next))
(set! next (+ next 1))
v))))
と同等です
(define count #f)
(set! count ( (lambda (next) ; close over `next`
(lambda () ; and then return lambda which _will_
(let ((v next)) ; read from `next`,
(set! next (+ v 1)) ; write new value to `next`,
v))) ; and then return the previous value;
0 )) ; `next` is initially 0
(これは「let-over-lambda」パターンです。その名前の Lisp の本さえあります)。
割り当てる値count
は一度だけ「計算」されます。この値は、のバインディングを参照するクロージャーnext
であり、その (バインディング) はその (クロージャー) の外部にあります。次に、が「使用」されるたび count
に、つまり参照先のプロシージャが呼び出されるたびに、プロシージャ (プロシージャ) はそのバインディングを参照します。最初にバインディングから読み取り、次に内容を変更します。ただし、初期値にリセットしません。バインディングは、その作成の一部として 1 回だけ開始されます。これは、クロージャの作成時に発生します。
このバインドは、このプロシージャからのみ表示されます。クロージャーは、このプロシージャーと、このバインディングを保持する環境フレームのバンドルです。このクロージャーは、式のレキシカル スコープ内で式(lambda () ...)
を評価した結果です。next
(lambda (next) ...)