我正在编写一个方案程序,该程序在最后用操作员评估列表。
示例:(评估'(1 2 +)) - > 3
我的函数适用于基本运算符(+, - ,*,/),但是当我有一个嵌套列表时会出现问题。
示例:(评估'(1(2 3 +)*)) - > (无)
我错过了一个条件吗?
(define (evaluate lis)
(cond
((not (list? lis))
lis)
((list? lis)
(if (equal? (length lis) 3)
(cond
((equal? (cddr lis) '(+))
(+ (car lis) (car (cdr lis))))
((equal? (cddr lis) '(-))
(- (car lis) (car (cdr lis))))
((equal? (cddr lis) '(*))
(* (car lis) (car (cdr lis))))
((equal? (cddr lis) '(/))
(/ (car lis) (car (cdr lis)))))))))
答案 0 :(得分:1)
我有三个指点:
如果其中一个参数是表达式,则表示您没有对其进行评估。从而。你需要在两个参数上运行postfix
。
如果长度不是3
,您可以让实现选择if
应返回的值。对于球拍#<void>
。也许你应该选择一些东西?
由于您的单词有一定数量的参数,因此不需要括号:
(define (peval exprs)
(define primitives `((+ . ,+) (- . ,-) (* . ,*) (/ . ,/)))
(foldl (lambda (operator operands)
(let ((aproc (assq operator primitives)))
(if aproc
(cons ((cdr aproc) (cadr operands) (car operands))
(cddr operands))
(cons operator operands))))
'()
exprs))
(peval '(2 3 4 + *)) ; (2 (3 4 +) *) == 14
请注意,这里的参数实际上是自动计算的。这就是连接语言(也就是堆栈语言)的用法。
答案 1 :(得分:0)
您忘记以递归方式调用子表达式上的过程。请参阅此处,我已将其重命名为!
以简化:
(define (! lis)
(cond
((not (list? lis))
lis)
((list? lis)
(if (equal? (length lis) 3)
(cond
((equal? (cddr lis) '(+))
(+ (! (car lis)) (! (cadr lis))))
((equal? (cddr lis) '(-))
(- (! (car lis)) (! (cadr lis))))
((equal? (cddr lis) '(*))
(* (! (car lis)) (! (cadr lis))))
((equal? (cddr lis) '(/))
(/ (! (car lis)) (! (cadr lis)))))))))
顺便提一下,以下是如何更加惯用地重写程序:
(define (evaluate lis)
(cond
((not (list? lis)) lis)
((= (length lis) 3)
(let ((op (case (caddr lis)
((+) +)
((-) -)
((*) *)
((/) /))))
(op (evaluate (car lis)) (evaluate (cadr lis)))))))