Reputation: 190
I am generating lists such as the following, with operators, numbers and parameters:
'(* (+ 3 param1) param2)
That I want to evaluate and test with different parameters. But reading around it doesn't look like I can change those values at runtime if I use the eval
procedure.
Is there a clean way to do this?
Upvotes: 2
Views: 630
Reputation: 27434
If you want to manage explicitly the binding of values to the variables in the expression, in order to evaluate the expression with different values, you could create and manipulate an explicit “environment”.
; create an empty environment
(define (make-env)
'())
; create a new environment extending env with a new bind (var . value)
(define (bind var value env)
(cons (cons var value) env))
; lookup var in env, if present returns the value, otherwise returns itself
(define (lookup var env)
(cond ((null? env) var)
((eq? (caar env) var) (cdar env))
(else (lookup var (cdr env)))))
(define (myEval exp env)
(define (substitute exp env)
(cond ((null? exp) '())
((number? exp) exp)
((symbol? exp) (lookup exp env))
(else (cons (substitute (car exp) env) (substitute (cdr exp) env)))))
(eval (substitute exp env)))
(myEval '(* (+ 3 param1) param2) (bind 'param1 10 (bind 'param2 20 (make-env))))
The function myEval
substitutes all the variables inside the expression with the corresponding value inside the environment, then call the predefined function eval
. Note that the definition of an environment is the first step in defining your own eval
function.
Upvotes: 1
Reputation: 236140
Here's an alternative, using quasiquoting:
(eval `(* (+ 3 ,param1) ,param2))
In the above line, the two parameters will get evaluated at runtime before the call to eval
. For example:
(define param1 42)
(define param2 43)
(eval `(* (+ 3 ,param1) ,param2))
=> 1935
Upvotes: 2
Reputation: 31145
Note that
> (eval '(let ([param1 42]
[param2 43])
(* (+ 3 param1) param2)))
1935
So wrap your expression in a let
before you evaluate it.
Upvotes: 1