Reputation: 3
I'm writing a scheme program that evaluates a list with the operator on the end.
Example: (evaluate '(1 2 +)) --> 3
I have the function working for basic operators (+, -, *, /) but the issue comes in when I have a nested list.
Example: (evaluate '(1 (2 3 +) *)) --> (nothing)
Am I missing a condition?
(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)))))))))
Upvotes: 0
Views: 327
Reputation: 48745
I have 3 pointers:
If one of the arguments are an expression you are not evaluating it. Thus. you need to run postfix
on both arguments as well.
When the length is not 3
you let the implementation choose what value the if
should return. For racket its #<void>
. Perhaps you should choose something?
Since you have a fixed number of arguments for your words there is no need for parentheses:
(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
Notice that here the arguments actually gets evaluates automatically. This is how the concatenating languages (aka stack languages) do it.
Upvotes: 1
Reputation: 679
You forgot to recursively call the procedure on the sub-expressions. See here, where I've renamed it !
for brevity:
(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)))))))))
Incidentally, here's how you might rewrite the program more idiomatically:
(define (evaluate lis)
(cond
((not (list? lis)) lis)
((= (length lis) 3)
(let ((op (case (caddr lis)
((+) +)
((-) -)
((*) *)
((/) /))))
(op (evaluate (car lis)) (evaluate (cadr lis)))))))
Upvotes: 0