[plt-scheme] Using eval in modules

From: Danny Yoo (dyoo at cs.wpi.edu)
Date: Sat Jun 23 12:49:07 EDT 2007


On Sat, 23 Jun 2007, Jean-Pierre Lozi wrote:

> This works because you are calling (eval-string-with-1 "abc") from 
> outside the module - but it doesn't when the function is called from the 
> inside the module. For instance :
>
> (module foo mzscheme
>  (define  (abc x)
>    (display "foo")
>    (newline))
>
>  (define  (eval-string-with-1 string)
>    ((eval (string->symbol string)) 1))
>
> (eval-string-with-1 "abc")
>
>  (provide eval-string-with-1
>           abc))
>
> (require foo)
>
> Doesn't work. And that's what I need to do :/

Hello Jean-Pierre Lozi,

Question: do you really need the full power of eval?  What are you really 
trying to do?


If you're trying to expose a few functions to the outside world for 
dynamic dispatch, then rather than eval, then would a simpler dispatch 
table approach work for you?

Here's what it might look like:

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(module foo mzscheme
   (require (lib "etc.ss"))

   (define (abc x)
     (display "foo")
     (newline))

   (define registered-handlers (hash-table 'equal
                                           ("abc" abc)))
   (define (eval-string-with-1 string)
     ((hash-table-get registered-handlers string) 1)))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

This requires no eval trickiness, and is much safer in terms of limiting 
what kind of mischief the caller can do.  If the user tries to eval 
something that's not in the dispatch table, we can reliably catch that 
kind of thing.

In contrast, the eval approach exposes the full power of the language, 
including all the primitives, so in your original approach, stuff like:

     (eval-string-with-1 "exit")

will kill the runtime.


Posted on the users mailing list.