I'm trying to level up on metaprogramming in Racket and realized I don't know how to take a datum and simply "eval" it.
If I have
(for ((x '(("Five" (+ 2 3))
("Twelve" (* 6 2))
("Three" (- (/ 21 3) 4)))))
(displayln (format "~s: ~s" (first x) (second x))))
I get
: "Five": (+ 2 3)
: "Twelve": (* 6 2)
: "Three": (- (/ 21 3) 4)
Which is not actually what I want - I want to actually evaluate that list to get the answer.
I'm sure this is simple (perhaps something I need to involve syntax for?) but I'm just missing the picture now. How do I do that?
Edit: I want to evaluate the s-exp just before displaying, not in the initial list. This is why I figure I might need syntax since I would (I think) have to inject the current syntax context.
Eval is almost always the wrong choice, but eval
is what you are looking for:
#lang racket
(define base-ns (make-base-namespace))
(for ((x '(("Five" (+ 2 3))
("Twelve" (* 6 2))
("Three" (- (/ 21 3) 4)))))
(displayln (format "~s: ~s" (first x) (eval (second x) base-ns))))
Alternative 1: Lambda / thunks
(for ((x `(("Five" ,(thunk (+ 2 3)))
("Twelve" ,(thunk (* 6 2)))
("Three" ,(thunk (- (/ 21 3) 4))))))
;; notice double parentheses to call the thunk
(displayln (format "~s: ~s" (first x) ((second x)))))
A thunk is just syntax sugar for a lambda with no arguments.
I've played a little around having procedures that can print their sources. Thus you can make your own thunk
that has the original structure as structure as I demonstrate with my visual lambda:
(struct proc (src obj)
#:property prop:procedure (struct-field-index obj)
#:transparent
#:methods gen:custom-write
[(define (write-proc x port mode)
((case mode
[(#t) write]
[(#f) display]
[else pretty-print])
(proc-src x)
port))])
(define-syntax lambda*
(syntax-rules ()
((_ . rest)
(proc '(lambda* . rest) (lambda . rest)))))
(define test (lambda* (x y) (+ x y)))
test ; ==> #(struct:closure (lambda* (x y) (+ x y)) #<procedure>)
(proc-src test) ; ==> (lambda* (x y) (+ x y))
(proc-obj test) ; ==> #<procedure>
((proc-obj test) 1 2) ; ==> 3
(test 1 2) ; ==> 3
(display test) ; prints (lambda* (x y) (+ x y))