Reputation: 24535
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
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