As noted in the comments, set!
is a primitive in Scheme that must be provided by the implementation. Similarly, you can't implement the assignment operator, =
, in most programming languages. In Common Lisp, setf
can be extended (using setf
-expanders) to allow (setf form value)
to work on new kinds of forms.
Because Scheme's set!
only modifies variable bindings (like Common Lisp's setq
), it is still worth asking how can we implement functions like set-car!
and other structural modifiers. This could be seen, in one sense, as a generalization of assignment to variables, but because lexical variables (along with closures) are sufficient to represent arbitrarily complex structures, it can also be seen as a more specialized case. In Scheme (aside from built in primitives like arrays), mutation of object fields is a specialization, because objects can be implemented by lexical closures, and implemented in terms of set!
. This is a typical exercise given when showing how structures, e.g., cons cells, can be implemented using lexical closures alone. Here's an example that shows the implementation of single-value mutable cells::
(define (make-cell value)
(lambda (op)
(case op
((update)
(lambda (new-value)
(set! value new-value)))
((retrieve)
(lambda ()
value)))))
(define (set-value! cell new-value)
((cell 'update) new-value))
(define (get-value cell)
((cell 'retrieve)))
Given these definitions, we can create a cell, that starts with the value 4
, update the value to 8
using our set-value!
, and retrieve the new value:
(let ((c (make-cell 4)))
(set-value! c 8)
(get-value c))
=> 8
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…