我实现了一个带有算术表达式并返回值的函数:
; 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))]))
任何人都可以告诉我,如果我朝着正确的方向前进并且可能会给我一个暗示吗?非常感谢!
答案 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
)]))
(通过这种方式,您如何知道是否存在未绑定的标识符?)
另见: