【问题标题】:SICP:'set' and 'define' in The Metacircular EvaluatorSICP:元循环评估器中的“设置”和“定义”
【发布时间】:2016-06-03 22:18:32
【问题描述】:

在评估和调用“set-variable-value!”时和'define-variable-value!',程序会将'env'传递给函数,在这两个函数中,'set!'只能修改函数内部的“env”;修改后的“env”也不会返回。

那么,如何更改“env”?

【问题讨论】:

    标签: scheme sicp


    【解决方案1】:

    请记住,在本书的第 3.3 节 Modeling with Mutable Data 中,通过使用在函数名称后缀 ! 的约定引入了可变运算符,就像在 set-car! 中一样,它修改了 cons 单元的 car .

    函数set-variable-value!define-variable-value! 只是修改传递的环境,因此不需要返回它。例如,set-variable-value! 是通过使用 set-car! 定义的:

    (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))
    

    请注意,作者在Chapter 4 的开头说:

    我们的评估器实现的语言将是我们在本书中使用的 Lisp 的 Scheme 方言的一个子集。

    由于引入的方言有副作用,实现它的最简单解决方案是在其解释器中也使用副作用。

    【讨论】:

    • 我很抱歉,但我还是不明白:当'env'被传递给这两个函数时,我真的认为它是'env'的副本(值)被传递,而不是原始的“env”本身。所以修改的是副本,但原始的仍然没有改变。并且有三个变量叫做'env',我想那是什么'set-car!' modifies 是 'env-loop' 的参数之一。
    • @EndKin ,在 Scheme 列表中是通过引用而不是通过复制传递的,因此修改从函数外部可见。
    • @EndKin:它被复制了。但是 env 持有的值是一个指向对结构的指针,因此通过复制它,您有两个指向同一个底层结构的指针,并且使用一个指针对结构所做的更改将通过另一个指针看到。您可以将 Scheme 中的所有值都视为指向事物的指针,就像在 Python 中一样。
    • @Renzo:Scheme 中只有值传递。
    • @newacct,是的,我现在。我以一种可能过于综合且可能具有误导性的方式说,如果将列表视为一个值,这在高级语言中可能是自然的,那么 那个 值(列表)不是复制,但对它的引用被复制(即通过)。我认为通过复制将整个结构作为值传递的想法是一件让很多人感到困惑的事情,而不是最后一个,因为“通过复制整个结构来传递结构”在许多现代语言中都存在。我同意,一般来说,应该更精确。
    猜你喜欢
    • 1970-01-01
    • 2018-09-26
    • 1970-01-01
    • 1970-01-01
    • 2015-12-13
    • 2016-03-23
    • 1970-01-01
    • 1970-01-01
    • 2010-10-02
    相关资源
    最近更新 更多