Warm tip: This article is reproduced from serverfault.com, please click

Comparing a variable to a character in Lisp

发布于 2020-12-02 18:43:53

I am new in lisp programming and I am trying to compare a variable let's say op to the characters +,-,*,/. But in every way I write the correct result doesn't show up. How could I rewrite the following code:

(defun evaluate(op o1 o2)
  (cond
    ( (string= op `+) (+ o1 o2))
    ( (string= op `-) (- o1 o2))
    ( (string= op `*) (* o1 o2))
    ( (string= op `/) (/ o1 o2))
  )
)

the input is:

(print (calculate `(- * + 4 3 2 5)))

So I get in my function the operator characters. Don't mind the numbers. To be sure here is the calculate function.

(defun calculate (l)
  (if (and (numberp (car l)) (not (null l)) )
      (car l)
    ( evaluate (car l) (calculate (cdr l) ) 
    (calculate (cdr l) ) )
  )
)
Questioner
Stefan
Viewed
0
Svante 2020-12-03 09:47:35

The way calculate is written, this evaluates (- (* (+ 4 4) (+ 4 4)) (* (+ 4 4) (+ 4 4))), which is 0. I don't know what you expect, but let's take a look at tracing (SO> is the repl prompt):

SO> (trace evaluate calculate)
(EVALUATE CALCULATE)
SO> (calculate '(- * + 4 3 2 5))
  0: (SO::CALCULATE (- * + 4 3 2 5))
    1: (SO::CALCULATE (* + 4 3 2 5))
      2: (SO::CALCULATE (+ 4 3 2 5))
        3: (SO::CALCULATE (4 3 2 5))
        3: CALCULATE returned 4
        3: (SO::CALCULATE (4 3 2 5))
        3: CALCULATE returned 4
        3: (SO::EVALUATE + 4 4)
        3: EVALUATE returned 8
      2: CALCULATE returned 8
      2: (SO::CALCULATE (+ 4 3 2 5))
        3: (SO::CALCULATE (4 3 2 5))
        3: CALCULATE returned 4
        3: (SO::CALCULATE (4 3 2 5))
        3: CALCULATE returned 4
        3: (SO::EVALUATE + 4 4)
        3: EVALUATE returned 8
      2: CALCULATE returned 8
      2: (SO::EVALUATE * 8 8)
      2: EVALUATE returned 64
    1: CALCULATE returned 64
    1: (SO::CALCULATE (* + 4 3 2 5))
      2: (SO::CALCULATE (+ 4 3 2 5))
        3: (SO::CALCULATE (4 3 2 5))
        3: CALCULATE returned 4
        3: (SO::CALCULATE (4 3 2 5))
        3: CALCULATE returned 4
        3: (SO::EVALUATE + 4 4)
        3: EVALUATE returned 8
      2: CALCULATE returned 8
      2: (SO::CALCULATE (+ 4 3 2 5))
        3: (SO::CALCULATE (4 3 2 5))
        3: CALCULATE returned 4
        3: (SO::CALCULATE (4 3 2 5))
        3: CALCULATE returned 4
        3: (SO::EVALUATE + 4 4)
        3: EVALUATE returned 8
      2: CALCULATE returned 8
      2: (SO::EVALUATE * 8 8)
      2: EVALUATE returned 64
    1: CALCULATE returned 64
    1: (SO::EVALUATE - 64 64)
    1: EVALUATE returned 0
  0: CALCULATE returned 0
0

That last 0 is the result. Of the numbers, only the first one is ever touched, and I guess you meant to use the others too.

It should be helpful to point out that the two calls to (calculate (cdr l)) inside of calculate will always produce the same result.

Side notes: