【问题标题】:racket: (evaluate t lst)球拍:(评估 t lst)
【发布时间】:2016-06-15 10:55:32
【问题描述】:

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

; 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))]))

谁能告诉我我是否朝着正确的方向前进并给我一个提示?将不胜感激!

【问题讨论】:

    标签: eval racket arithmetic-expressions


    【解决方案1】:

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

    (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)))称为环境。当您看到一个符号时,您只需在环境中查找并返回与您正在查找的符号相关联的值。

    ; 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
                 )]))
    

    (通过这种方式,你怎么知道是否有未绑定的标识符?)

    另见:

    【讨论】:

      猜你喜欢
      • 2012-05-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-04-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多