从不同的环境返回变量

Returning variable from a different environment

我正在尝试 return 不同环境范围内的变量。 我目前拥有的是

(define make-empty-env
   (lambda()
      (make-top-level-environment)
   )
)

当您从解释器中调用它时,它会创建一个新环境 即(定义环境(make-empty-env))

如果我在 "env" 中将变量 "a" 定义为 15,我的目标是 return 通过从用户初始环境调用的函数来获得此值。

类似于

(apply-env env 'v) 输出 -> 环境范围内变量 v 的值。 v 在 user-initial-environment 中可以是未定义的,但如果变量存在于 env 中,它仍然是 return 一个值。

我试过:

(define apply-env
   (lambda (env v)
       (eval (+ v 0) env)
   )
)

这不起作用,因为我在调用该函数时传递了一个符号 'v。我的主要问题是我不知道如何传递符号并将其视为函数中的变量。这是作业,函数的提示是:

(apply-env env v)

Returns the value of variable v in environment env.

Here are some calls to apply-env:

In test-env, a = 1, b = 2

(apply-env test-env 'a) 1

(apply-env test-env 'b) 2

我对 scheme 比较陌生,所以我可能缺少一些基础知识,非常感谢任何指点或帮助。

据我所知,环境变量的设计实现由您决定。由于这是一个家庭作业问题,我假设您可以按照自己喜欢的方式进行(我假设)。

假设您想将环境变量设为 2 个元素的列表。

env -> ((var1,val1),(var2,val2),......,(varn.valn))

E.g.

env -> ((a,1),(b,2),(c,3))

现在,当您想要 "create" 初始环境时,您只需调用一个 returns 初始环境 的函数。现在我们的环境变量 env 只是一个空列表 '()。你可以做一个这样的函数

(define (make-empty-env)
    (lambda ()
        '()
    )
)

现在要在 env 中添加、删除和更新变量,您可以为基础数据结构实现 carcdr 以及 in-env? 等功能


;;; cdr like function for env
(define (cdr-env env)
    (cdr env)
)

;;; car like function for env
(define (car-env)
    (list (car env))
)

;;; Returns boolean for v in env
(define (in-env? env)
    (cond
        ((null? env)    ; If env is empty then v doesnt exist in env
            #f
        )
        ((equal? v (car (car env))) ; If first element of the first list in env matches with v 
            #t
        )
        (else       ; Recursive step to find if v is in the remaining enviornment env
            (in-env? v (cdr env))
        )
    )
)

使用这些函数,您可以相对轻松地实现 env.

的插入、检索和更新功能

;;; Update the value variable v to val in env. This function assumes that you are calling it in the insert-env function
(define (update-env v val env)
    (cond 
        ((null? env)
            '()
        )
        ((equal? v (car (car env)))
            (append (cdr env) (list (list v val)))
        )
        (else
            (append 
                (update-env v val (cdr env)) 
                (list (list (car (car env)) (car (cdr (car env)))))
            )
        )
    )
)


;;; add a variable-value pair (v,val) to env, also checks if variable already exists in pair. If so then updates it
(define (insert-env v val env)
    (cond 
        ((in-env? v env)
            (update-env v val env)
        )
        (else  ; Add to env the 2 element list (v val)
            (append env (list (list v val)))
        )
    )
)

;;; Gets the value of variable v or returns an error message
(define apply-env
    (lambda (env v)
        (cond 
            ((null? env)    ; If env is empty then no variablles exist for the name v
                (error "appply-env: found empty enviroment")
            )
            ((equal? (car (car env)) v) ; First element of the first list is v [matching var found in env]
                (car (cdr (car env))) ; Second element of that list is value of v
            )
            (else       ; Else look for v in the rest of the env list
                (apply-env (cdr env) v) 
            )
        )
    )
)

NOTE: Your implementations of functions like above for env will depend on how you choose to implement the data structure that will store your variable bindings in env You can use any data structure you like. E.g. Binary tree. stack, queue, etc

希望对您有所帮助!

问题是添加没有暂存。使用准引号考虑以下内容:

(define apply-env
   (lambda (env v)
       (eval `(+ ,v 0) env)
   )
)

准引号相当于(list '+ v 0).