そのような突然変異を許容することは素晴らしいことです。これにより、事前に準備された手段を介してのみアクセスできる内部状態を持つオブジェクトを定義できます。
(define (adder n)
(let ((x n))
(lambda (y)
(cond ((pair? y) (set! x (car y)))
(else (+ x y))))))
(define f (adder 1))
(f 5) ; 6
(f (list 10))
(f 5) ; 15
関数とその確立されたプロトコルを使用するx
以外に、それを変更する方法はありません- まさにSchemeのレキシカルスコープのためです。f
変数は、内部が定義されてx
いるものに属する内部環境フレーム内のメモリ セルを参照します。つまり、"クロージャ" とも呼ばれる、 とその定義環境の組み合わせを返します。let
lambda
lambda
そして、この内部変数を変更するためのプロトコルを提供しない場合、それを変更することはできません。
(set! x 5) ; WRONG: "x", what "x"? it's inaccessible!
編集:あなたの質問の意味を完全に変えるあなたの新しいコードは、そこにも問題はありません。私たちはまだその定義環境の中にいるようなものなので、当然、内部変数には引き続きアクセスできます。
さらに問題なのは以下
(define x 1)
(define (f y) (+ x y))
(define x 4)
(f 5) ;?? it's 9.
私は 2 番目の定義が最初の定義に干渉しないことを期待していますが、R5RS はトップレベルのdefine
ようなものだと言っています。set!
クロージャは、定義環境を一緒にパッケージ化します。最上位環境は常にアクセス可能です。
参照する変数x
はf
最上位環境に存在するため、同じスコープ内の任意のコードからアクセスできます。つまり、任意のコードです。