rnso
rnso

Reputation: 24535

Eval not working in Racket

I am using following code modified from Solving Infix Arithmatic in LISP with definition of atom from Check if an argument is a list or an atom to have an infix arithmetic solver:

(define atom? (or/c number? symbol? boolean? string?)) 

(define (solve expression)
  (define templist '())
  (println expression)
  (if (atom? expression)
      expression
      (begin
        (set! templist (list (second expression)
                             (solve (first expression))
                             (solve (third expression))  ))
        (println templist)
        (eval templist) ) ) )

(solve '(3 + 2))

The output is as follows:

'(3 + 2)
3
2
'(+ 3 2)
+: unbound identifier;
 also, no #%app syntax transformer is bound in: +

Hence, the templist is created all right (+ 3 2) but there is error at eval level. Why is '+' seen as an 'unbound identifier'? The eval function otherwise works well on the command line in DrRacket:

> (eval '(+ 3 2))
5

Where is the problem and how can it be solved? Thanks.

Upvotes: 1

Views: 804

Answers (1)

Alexis King
Alexis King

Reputation: 43852

Have you not been learning from the answers to your previous questions? Do not use set!, it is not good Scheme/Racket style. It’s especially egregious here because it is doing absolutely nothing at all; take it out and use let (or local, or block with internal definitions, if you’d prefer).

That aside, eval is equally evil, and you don’t need it here. Functions are first class; create a mapping between symbols and functions, then just use the mapping to fetch the relevant function to invoke.

(define (operator->procedure op)
  (case op
    [(+) +]
    [(-) -]
    [(*) *]
    [(/) /]
    [else (error 'operator->procedure "unknown operator ~v" op)]))

(define (solve expression)
  (if (atom? expression)
      expression
      ((operator->procedure (second expression))
       (solve (first expression))
       (solve (third expression)))))

To be even clearer, you could use Racket’s pattern-matching form, match:

(define (solve expression)
  (match expression
    [(? atom) expression]
    [(list a op b)
     ((operator->procedure op) (solve a) (solve b))]))

Upvotes: 3

Related Questions