HedgepigMatt
HedgepigMatt

Reputation: 190

Evaluate list in Racket with parameters

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

Answers (3)

Renzo
Renzo

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

Óscar López
Óscar López

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

soegaard
soegaard

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

Related Questions