【问题标题】:Create environment with variables in Scheme在 Scheme 中使用变量创建环境
【发布时间】:2018-07-24 12:48:58
【问题描述】:

我希望创建类似于 OOP 中的对象或环境的东西

这就是我的想法:

(define env (variable 'x 10 env))

我在其中定义了一个环境并在该环境中创建了一个值为 10 的变量。

我还希望能够调用该环境中的价值观。例如

(get-value env 'x)
> 10

我最多能理解的是它涉及closures,但我不知道从哪里开始

【问题讨论】:

  • 没有必要涉及闭包。您需要熟悉列表以及如何在其中查找具有特定属性的事物。

标签: oop functional-programming closures scheme racket


【解决方案1】:

有很多方法可以做到这一点。 classical way 是使用 alist:

(define (variable name value env)
  (cons (cons name value) env))

(define (get-value name env)
  (let ((val (assq name env)))
    (if val 
        (cdr val)
        (error "Unbound variable" name)))) ;  for r6rs use raise

;; the empty environment
(define the-empty-environment '())

Al Petrofsky 制作了 eiod(一个定义中的 Eval),它是这样做的:

;; actually called extend
(define (variable name value env)
  (lambda (i) (if (eq? name i) value (env i)))

;; just a wrapper, no need for it since you can just call env with the name
(define (get-value name env)
  (env name))

;; the empty environment
(define (the-empty-environment i) 
  (error "Unbound variable" i))

在SICP 中,您有带有绑定的框架:

;; actually called extend-environment
(define (variables vars vals env)
  (if (= (length vars) (length vals))
      (cons (make-frame vars vals) env)
      (if (< (length vars) (length vals))
          (error "Too many arguments supplied" vars vals)
          (error "Too few arguments supplied" vars vals))))

;; actualy called lookup-variable-value 
(define (get-value var env)
  (define (env-loop env)
    (define (scan vars vals)
      (cond ((null? vars)
             (env-loop (enclosing-environment env)))
            ((eq? var (car vars))
             (car vals))
            (else (scan (cdr vars) (cdr vals)))))
    (if (eq? env the-empty-environment)
        (error "Unbound variable" var)
        (let ((frame (first-frame env)))
          (scan (frame-variables frame)
                (frame-values frame)))))
  (env-loop env))


;; the empty environment
(define the-empty-environment '())

;; referenced
(define (enclosing-environment env) (cdr env))
(define (first-frame env) (car env))
(define (make-frame variables values)
  (cons variables values))
(define (frame-variables frame) (car frame))
(define (frame-values frame) (cdr frame))

请注意,与其他添加一个的不同,这会添加一整套。例如。将x 绑定到5 和y 到7 你这样做:

(variables '(x y)  '(5 7) env)

我将对此添加自己的看法:

(define (variable var val env)
  (hash-set env var val))

(define (get-value name env)
  (hash-ref env name (lambda () (error "Unbound variable" name))))

;; the empty environment
(define the-empty-environment '#hasheq()) 

这个答案的重点是,鉴于您可以选择get-value、variable 和the-empty-environment 的设计。只要你能实现这些,它是如何完成的并不重要。您可以将一个替换为另一个,解释器仍然可以工作。除了需要您一次执行一帧的 SICP 之外。

【讨论】:

    【解决方案2】:

    实现这一点的最简单方法是使用 alist。上面的variable和get-value可以定义如下:

    (define (variable name value env) (cons (cons name value) env))
    (define (get-value name env) (cond ((assq name env) => cdr) (else #f)))
    

    初始环境为'(),如果要隐藏空列表也可以这样定义:

    (define initial-env '())
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-05-11
      • 1970-01-01
      • 2019-01-15
      • 1970-01-01
      • 2021-07-18
      • 1970-01-01
      • 2021-11-09
      相关资源
      最近更新 更多