我正在尝试实现执行以下操作的函数(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}}
任何帮助将不胜感激!
答案 0 :(得分:4)
这里的技巧是要理解表达式可以采用两种形式:原始数据或包含操作的列表。作为伪语法,这意味着每个表达式必须符合以下结构:
expression = number | ( expression operator expression ) operator = + | - | * | /
这意味着eval
函数必须能够处理 类型的表达式,因此所有这些都应该有效:
(eval 7) ; => 7
(eval '(1 + 6)) ; => 7
(eval '((2 * 3) + 1) ; => 7
从中可以采取两件事:
eval
函数应该能够处理原始数字,而不仅仅是包含运算符的列表。eval
函数中只需要处理两种情况。这意味着eval
应该采用以下形式:
; eval : expression? -> number?
(define (eval expr)
(cond
[(number? x) ???]
[else ???]))
您实施eval
的许多不同案例过于复杂且不必要。您不需要检查列表的结构,因为它总是需要以相同的方式进行评估:eval
左侧,然后eval
右侧,然后将两侧与操作组合在一起在中间。这是有效的,因为如果eval
可以处理数字,那么(eval 3)
之类的内容就能正常运行。
这听起来像是一个家庭作业问题,所以我不会放弃精确的实施,但希望这足以让你指出正确的方向。