球拍:(评价t lst)

时间:2016-06-15 10:55:33

标签: eval racket arithmetic-expressions

我实现了一个带有算术表达式并返回值的函数:

; an arithmetic expression (t) is one of the following:
; - a number
; - a list of the form '(a operator b) where a and b are arithmetic expressions
; arithmetic expression -> number

; computes the value of the arithmetic expression

(define (eval t)
  (cond
    [(number? t) t]
    [else ((cond
            [(equal? (second t) '+) +]
            [(equal? (second t) '-) -]
            [(equal? (second t) '*) *]
            [(equal? (second t) '/) /])
           (eval (first t)) (eval (third t)))]))   

它完美无缺,但显然它不能占用常数。所以我要做的是扩展程序,使其适用于:

(eval '(1 + (3 * x)) (make-const 'x 3)                     -> 10
(eval '((3 - x) * y) ((make-const 'x 1) (make-const 'y 2)) -> 4
(eval '(1 + (y * x)) (make-const 'x 3)                     -> "error"

我的想法是定义一个结构:

(define struct const (symbol number))


(define (eval. t x)
  (cond
    [(number? t) t]
    [(symbol?  t) ???]
    [else ((cond
            [(equal? (second t) '+) +]
            [(equal? (second t) '-) -]
            [(equal? (second t) '*) *]
            [(equal? (second t) '/) /])
           (eval. (first t) lst) (eval. (third t) lst))]))

任何人都可以告诉我,如果我朝着正确的方向前进并且可能会给我一个暗示吗?非常感谢!

1 个答案:

答案 0 :(得分:2)

首先,请注意您的示例略有错误:

(eval '(1 + (3 * x)) (make-const 'x 3)
; you need a closing parenthesis

(eval '((3 - x) * y) ((make-const 'x 1) (make-const 'y 2))
; same as above. also, ((make-const 'x 1) (make-const 'y 2)) doesn't make
; sense. Do you mean (list (make-const 'x 1) (make-const 'y 2))

无论如何,有两种方法可以做到这一点。

第一种方法是使eval有两个阶段:第一阶段是首先替换所有变量。如果事情进展顺利,你会得到一个没有标识符的表达式。第二步是调用eval的第一个版本(我将其称为eval-helper)。

; eval :: expr, listof const -> number
(define (eval t vars)
  (eval-helper (subst-all t vars)))

确实,困难的部分是让subst-all正确。为简化起见,您可能希望编写一个名为subst的函数,该函数一次只能替换一个标识符。这可以通过表达式的递归来完成,如果符号匹配则用符号替换符号。然后subst-all可以使用subst作为辅助函数。

(通过这种方式,您如何知道是否存在未绑定的标识符?)

第二种方法是遵循您的代码模板:

(define struct const (symbol number))

(define (eval t env)
  (cond
    [(number? t) t]
    [(symbol?  t) ???]
    [else ((cond
            [(equal? (second t) '+) +]
            [(equal? (second t) '-) -]
            [(equal? (second t) '*) *]
            [(equal? (second t) '/) /])
           (eval (first t) env) (eval (third t) env))]))

通常,此函数的第二个参数(例如(list (make-const 'x 1) (make-const 'y 2)))称为 environment 。当您看到符号时,您只需查找环境并返回与您正在查找的符号关联的值。

; lookup :: symbol, listof const -> number
(define (lookup sym env)
  (cond
   [(empty? env) ???]
   [else (if (equal? sym (const-symbol (first env)))
             ??? ; you want to return the value!
             ??? ; recursively call lookup on the rest of the environment
             )]))

(通过这种方式,您如何知道是否存在未绑定的标识符?)

另见: