This seems like a simple question; perhaps it is so simple that it is difficult to find a search that will find the answer. In Scheme (specifically, the Guile implementation if that makes any difference) how do I evaluate something that has been quoted?
Here's what I'm trying to do.
I basically need to ensure that a function I define gets its arguments evaluated in a specific order, because side effects caused by evaluating one argument are depended on during the evaluation of other arguments. However, Scheme says arguments can be evaluated in any order, so I want to manually force it by quoting the arguments and then manually evaluating them in the order that is needed.
It appears that "eval" is supposed to do what I want, but it has two problems:
I've tried other tricks, like building up a lambda:
(list 'lambda '() '(car (b c)))
but it appears that this would then have to be evaluated to generate a procedure. I also tried:
(list lambda '() '(car (b c)))
but this returns a "primitive-builtin-macro" which doesn't work either.
Edit: Looks like a macro will work for controlling order of evaluation: (defmacro test1 (a b) `(begin ,b ,a))
eval
is utterly the wrong tool for just changing the order of evaluation of arguments. Create a macro instead:
;; (my-fun e1 e2)
;; Just calls my-real-fun, but evaluates e2 before e1
(define-syntax my-fun
(syntax-rules ()
[(my-fun e1 e2)
;; let* has guaranteed order of evaluation
(let* ([y e2]
[x e1])
(my-real-fun x y))]))
(define (my-real-fun x y) ....)
Or use defmacro
, if you must.
If you need to evaluate a list structure (nested lists with quoted symbols that represent a Scheme program text), then you should use eval
. Scheme requires passing an environment as a second argument, even if it is the current environment:
(eval '(+ x y) (interaction-environment))
If you just need to do your calculations in a particular order, you can enforce the order of evaluation for side effects by using begin
, let
, or just a function body. They define a sequence of evaluations:
(let ((x 42))
; eval with effects #1
(display x)
; eval with effects #2
(display (+ x 1)))
Edit: If you need to have a parametrized block of code where you can pass expressions unevaluated and then force their evaluation in some particular order, then you may use one of these techniques:
A macro (as you've mentioned already, just for completeness):
> (defmacro test1 (a b) `(begin ,b ,a))
> (test1 (display 2) (display 3)
32
A delayed computation (Scheme's special syntax for lazy evaluation):
> (define (test1 a b) (begin (force b) (force a)))
> (test1 (delay (display 2)) (delay (display 3)))
32
A regular lambda abstraction and application
> (define (test1 a b) (begin (b) (a)))
> (test1 (lambda () (display 2)) (lambda () (display 3)))
32
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With