Scheme: Proper application of the eval function?

2.5k views Asked by At

at work I encountered a basic problem when trying to implement a configuration script with Scheme. To avoid the need of inventing an artificial and restricted language the script should contain actual code. This code shall be evaluated later on. To make the configuration work as desired it has to have access to certain variables. These variables are only known in the context of the evaluation. Therefore the configuration script has to be evaluated in the current environment. Here is a primitive example of what I am talking about:

(let ((a #t))
  (wr "a is ..."
    (eval '(if a "true" "false"))))

When running this code I'd always get an error message telling me that the variable 'a' is unknown. So the question is: Do you know how to evaluate frozen code inside the current environment?

P.S.: I use the bigloo compiler.

///////////////////////////////////////////// EDIT: //////////////////////////////////////////////////////

When using the approach suggested by Chris I came to another interesting problem, the usage of the case keyword. The following two examples both use the same case construction which should trigger the output of a "yes!" line. Unfortunately they behave differently.

Usual -> output is "yes!" as expected:

  (define testit "test")
  (case testit
    (("test")
     (begin (newline) (write "yes!") (newline)))
    (else
      (begin (newline) (write "no!") (newline)))))

With eval -> output is surprisingly "no":

  (define env (null-environment 5))
  (eval '(define testit "test") env)
  (eval '(case testit
           (("test")
            (begin (newline) (write "yes!") (newline)))
           (else
            (begin (newline) (write "no!") (newline))))) 

Does that make any sense?

2

There are 2 answers

2
C. K. Young On BEST ANSWER

eval cannot access lexical variables, such as those defined using let.

Instead, you have to create an environment, and populate it with the variables you want to make available. For example:

(define env (null-environment 5))
(eval '(define a #t) env)
(wr "a is ..."
    (eval '(if a "true" "false") env))
0
roderic On

To answer your edit, you aren't passing env as an argument to the last eval. testit doesn't exist in the environment that eval creates if that argument isn't given.

That may be a typo, but if not, that's your problem.