Scheme 程序不评估嵌套列表?
Scheme program not evaluating nested lists?
我正在编写一个方案程序,该程序评估最后带有运算符的列表。
示例:(计算'(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)))))))))
您忘记了对子表达式递归调用过程。请参阅此处,为简洁起见,我将其重命名为 !
:
(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)))))))
我有 3 个建议:
如果其中一个参数是表达式,则您不会对其求值。因此。您还需要 运行 postfix
两个参数。
当长度不是 3
时,您让实现选择 if
应该 return 的值。对于球拍 #<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 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)))))))))
您忘记了对子表达式递归调用过程。请参阅此处,为简洁起见,我将其重命名为 !
:
(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)))))))
我有 3 个建议:
如果其中一个参数是表达式,则您不会对其求值。因此。您还需要 运行 postfix
两个参数。
当长度不是 3
时,您让实现选择 if
应该 return 的值。对于球拍 #<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
注意这里的参数实际上是自动求值的。这就是连接语言(又名堆栈语言)的工作方式。