怎么设置!计划中定义的?

Ara*_*idi 1 lisp scheme

你如何set!在Scheme中实现自己的功能?甲set!功能是改变被定义考虑到先前的值的值的破坏性过程.

Jos*_*lor 7

如评论set!中所述,Scheme中的原语必须由实现提供.同样,=在大多数编程语言中,您无法实现赋值运算符.在Common Lisp中,setf可以扩展(使用setf-expanders)以允许(setf form value)处理新类型的表单.

因为Scheme set!只修改了变量绑定(比如Common Lisp setq),所以仍然值得问我们如何实现像set-car!其他结构修饰符这样的函数.从某种意义上说,这可以看作是对变量赋值的概括,但是因为词汇变量(连同闭包)足以表示任意复杂的结构,所以它也可以被视为更专业的情况.在Scheme中(除了数组之类的内置原语),对象字段的变异是一种特殊化,因为对象可以通过词法闭包来实现,并且可以实现set!.这是一个典型的练习,展示了如何单独使用词法闭包来实现结构,例如cons单元.这是一个显示单值可变单元格实现的示例::

(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)))
Run Code Online (Sandbox Code Playgroud)

给定这些定义,我们可以创建一个以值开头的单元格,将值4更新为8使用我们的值set-value!,并检索新值:

(let ((c (make-cell 4)))
  (set-value! c 8)
  (get-value c))
=> 8
Run Code Online (Sandbox Code Playgroud)


Ósc*_*pez 6

如上所述,set!是一个原始的,不能作为一个程序来实现.为了真正理解它是如何工作的,我建议你看一下Lisp解释器的内部工作原理.这里是一个伟大的开始:在自循环直译器SICP,特别是标题为"分配和定义".以下是与问题相关的部分的摘录:

(define (eval exp env)
  (cond ...
        ((assignment? exp) (eval-assignment exp env))
        ...
        (else (error "Unknown expression type -- EVAL" exp))))

(define (assignment? exp)
  (tagged-list? exp 'set!))

(define (eval-assignment exp env)
  (set-variable-value! (assignment-variable exp)
                       (eval (assignment-value exp) env)
                       env)
  'ok)

(define (set-variable-value! var val env)
  (define (env-loop env)
    (define (scan vars vals)
      (cond ((null? vars)
             (env-loop (enclosing-environment env)))
            ((eq? var (car vars))
             (set-car! vals val))
            (else (scan (cdr vars) (cdr vals)))))
    (if (eq? env the-empty-environment)
        (error "Unbound variable -- SET!" var)
        (let ((frame (first-frame env)))
          (scan (frame-variables frame)
                (frame-values frame)))))
  (env-loop env))
Run Code Online (Sandbox Code Playgroud)

最后,set!操作只是环境中绑定值的变异.由于此级别的修改对于"正常"过程是禁止的,因此必须将其实现为特殊形式.