Reputation: 23
I'm trying to write a program which takes polynomials, and simplifies them. Every time I run the program, by calling "(evalexp '( (x 2) (z 8) ) p1)" I get the error, "Car: + is not a list". It is supposed to return "(+ 2 (* 2 (- y 4)))" Here is my code:
(setq p1 '(+ x (* x (- y (/ z 2)))))
(setq p2 '(+ (- z 2) (* x 5)))
(setq p3 '(+ 1 a))
(setq p4 '(+ x (+ x (* x 0))))
(defun addexp (e1 e2) (list '+ e1 e2))
(defun subexp (e1 e2) (list '- e1 e2))
(defun mulexp (e1 e2) (list '* e1 e2))
(defun divexp (e1 e2) (list '/ e1 e2))
(defun deep-subst (old new expr)
(cond
((null expr)
nil
)
((listp (car expr))
(cons (deep-subst old new (car expr)) (deep-subst old new (cdr expr)))
)
((eq old (car expr))
(cons new (deep-subst old new (cdr expr)))
)
(T
(cons (car expr) (deep-subst old new (cdr expr)))
)
)
)
(defun subst-bindings (expr bindinglist)
(cond
((null bindinglist)
expr )
(T
(deep-subst (car (car bindinglist)) (car (cdr (car bindinglist)))
(subst-bindings expr (cdr bindinglist))
))))
(defun simplify-triple(op left-arg right-arg)
(cond
((and (numberp left-arg) (numberp right-arg))
(eval (list op left-arg right-arg))
)
((and (eq op '+) (eql right-arg 0))
left-arg
)
((and (eq op '+) (eql left-arg 0))
right-arg
)
((and (eq op '-) (eql right-arg 0))
left-arg
)
((and (eq op '-) (eql right-arg left-arg))
0
)
((and (eq op '*) (eql right-arg 0))
0
)
((and (eq op '*) (eql left-arg 0))
0
)
((and (eq op '*) (eql right-arg 1))
left-arg
)
((and (eq op '*) (eql left-arg 1))
right-arg
)
((and (eq op '/) (eql left-arg 0))
0
)
((and (eq op '/) (eql right-arg 1))
left-arg
)
((and (eq op '/) (eql right-arg left-arg))
1
)
(T
(list op left-arg (simplify right-arg))
;(list op right-arg (simplify left-arg))
)
)
)
(defun simplify (exp)
(cond
( (listp exp)
(simplify-triple (car exp) (simplify (car (cdr exp))) (simplify (car (cdr (cdr exp)))))
)
(T
exp)))
(defun evalexp (exp binding-list)
(simplify (subst-bindings exp binding-list))
)
Upvotes: 2
Views: 1864
Reputation: 407
Found your bug. Most of your functions are declared to receive the expression as the first argument and the bindings as the second one, yet on your example you are calling the function passing the bindings as the first argument and the expression as the second. You must either call (evalexp p1 '((x 2) (z 8)))
or swap the argument order on your function definitions (I'd suggest this solution, as it seems more natural and looks like the assignment @rainer-joswig linked).
Particularly, subst-bindings
and evalexp
are the ones which need the change.
Upvotes: 3