Reputation: 182
Suppose somewhere I have defined several symbols:
#lang racket
(define foo 123)
(define bar '("1" "2" "3"))
I need a way to produce a string like "foo = 123"
or "bar = '("1" "2" "3")"
. I wrote a function for that:
(define (f2 sy)
(format "~a = ~s" sy (eval sy)))
This function works in the interpretator window pretty well.
> (f2 'foo)
"foo = 123"
> (f2 'bar)
"bar = (\"1\" \"2\" \"3\")"
That is quite satisfactory for me. However, when I use it in the code, I get
foo: unbound identifier;
also, no #%top syntax transformer is bound in: foo
I have a feeling that I am doing something wrong. Can you please suggest the right way to solve my problem?
P.S.: I am using DrRacket, version 5.3.1
Upvotes: 1
Views: 188
Reputation: 182
Another solution, also inspired by Asumu Takikawa uses the trick described in the guide:
(define-namespace-anchor a)
(define ns (namespace-anchor->namespace a))
(define (f2 sy)
(format "~a = ~s" sy (eval sy ns)))
On the contrast to the solution with macros, this function can be mapped.
Upvotes: 1
Reputation: 8523
First of all, eval
should really only be used as a last resort in Racket. It makes your program less efficient and harder to understand. The right way to do this is probably to write a macro such as the following:
(define-syntax-rule (f2 sy)
(format "~a = ~s" (quote sy) sy))
(define foo 2)
(f2 foo)
This macro just substitutes the name of the variable you want to lookup into the format expression in the body. The quote
turns the variable name into a symbol you can print. This macro doesn't work as a procedure, because (f2 foo)
would deference foo
before you can quote
and print its name.
Note: the reason why your eval
doesn't work as expected is because eval
always evaluates with respect to a namespace, which dictates what is in scope. The default namespace within a module has nothing in it, so eval
can't see foo
or anything else. You can read more about namespaces in the Guide.
Upvotes: 1