球拍:实现功能(评估t)

时间:2016-06-14 16:43:59

标签: list scheme eval racket

我正在尝试实现执行以下操作的函数(eval t):

的示例:

(define (inner lst)
  ((cond
     ((equal? (second lst) '+) +)
     ((equal? (second lst) '-) -)
     ((equal? (second lst) '*) *)
     ((equal? (second lst) '/) /))
   (first lst) (third lst)))


(define (eval t)
  (cond
    ((and (number? (first t)) (number? (third t))) (inner t))
    ((list? (third t)) (eval `(,(first t) ,(second t) ,(inner (third t)))))
    ((list? (first t)) (eval `(,(inner (first t)) ,(second t) ,(third t))))))

到目前为止我所拥有的是:

(eval '(1 + (1 + 2))) -> 4

(eval '((1 + 1) + (2 + 2))) -> 6

适用于:

(eval '((1 + 1) + (1 + (1 + 1))))

但它不适用于以下情况:

{{1}}

任何帮助将不胜感激!

1 个答案:

答案 0 :(得分:4)

这里的技巧是要理解表达式可以采用两种形式:原始数据或包含操作的列表。作为伪语法,这意味着每个表达式必须符合以下结构:

expression = number
           | ( expression operator expression )

operator   = +
           | -
           | *
           | /

这意味着eval函数必须能够处理 类型的表达式,因此所有这些都应该有效:

(eval 7)             ; => 7
(eval '(1 + 6))      ; => 7
(eval '((2 * 3) + 1) ; => 7

从中可以采取两件事:

  1. eval函数应该能够处理原始数字,而不仅仅是包含运算符的列表。
  2. eval函数中只需要处理两种情况。
  3. 这意味着eval应该采用以下形式:

    ; eval : expression? -> number?
    (define (eval expr)
      (cond
        [(number? x) ???]
        [else        ???]))
    

    您实施eval的许多不同案例过于复杂且不必要。您不需要检查列表的结构,因为它总是需要以相同的方式进行评估:eval左侧,然后eval右侧,然后将两侧与操作组合在一起在中间。这是有效的,因为如果eval可以处理数字,那么(eval 3)之类的内容就能正常运行。

    这听起来像是一个家庭作业问题,所以我不会放弃精确的实施,但希望这足以让你指出正确的方向。