Eval
Overview
The eval
function in Gerbil Scheme is a powerful tool for dynamic code execution. However, its behavior and usage differ between runtime and compile-time, and it has some key differences compared to Gambit Scheme. This document outlines how to use eval
effectively in various scenarios.
Runtime Behavior
Interactive Environment
In the Gerbil interpreter (gxi
), eval
works similarly to other Scheme implementations:
> (def greeting "hello world")
> (eval '(displayln greeting))
hello world
Compiled Binaries
When using eval
in compiled binaries, additional steps are necessary.
To demonstrate this let's slightly modify code from previous example, save it into the file:
eval-example.ss
(export main)
(def greeting "hello world")
(def (main . args)
(eval '(displayln greeting)))
Then compile into executable and run:
$ gxc -exe eval-example.ss
...
$ ./eval-example
*** ERROR -- Unbound variable: greeting
--- continuation backtrace:
[0] ##primordial-exception-handler-hook
An error is reported because eval operates on top-level namespace while greeting
is defined a module namespace which is added implicitly.
This may be fixed by adding a namespace to greeting
:
(export main)
(def greeting "hello world")
(def (main . args)
(eval '(displayln eval-example#greeting))
$ gxc -exe eval-example.ss
...
$ ./eval-example
hello world
Adding namespace to each symbol referenced under eval
may be a bit tedious, there is a better way to do this with (extern ...)
form.
Eval expression may be modified to look like this:
(begin
(extern namespace: eval-example
greeting)
(displayln greeting))
Using extern
will make eval-example#greeting
available as greeting
at runtime. But there is one more thing to do before it will work without errors, because extern
relies on :gerbil/expander
which should be loaded. In interactive mode this happens implicitly, while inside compiled binaries expander need to be loaded manually. Here is the final version:
(import :gerbil/expander)
(export main)
(def greeting "hello world")
(def (main . args)
(gerbil-load-expander!)
(eval '(begin
(extern namespace: eval-example
greeting)
(displayln greeting))))
Which works as expected:
$ gxc -exe eval-example.ss
...
$ ./eval-example
hello world