I am making an application using Racket in which Racket is also used as a scripting language. I want users to write scripts utilizing some structs and procedures provided in my executable.
For example I have userruntime.rkt:
(struct result (x y z))
(provide (all-from-out racket/base))
(provide (struct-out result))
And user writes script.rkt:
(define (my-even? x)
(if (eq? x 0) #t
(not (my-odd? (sub1 x)))))
(define (my-odd? x)
(not (my-even? (sub1 x))))
(result (my-odd? 1) (my-odd? 2) (my-odd? 3))
I want to evaluate to the following result (you get the idea):
'(#<void> #<void> (result #t #f #t))
It seems that make-module-evaluator in racket/sandbox satisfies my needs. However I failed to find a way to pass the module (as a file compiled and linked in the final executable). The official documentation gives the following example:
(define base-module-eval
(make-evaluator 'racket/base '(define (f) later)
'(define later 5)))
Which is not requiring a file. When I try:
(make-module-evaluator "userruntime.rkt") ; make-module-evaluator: expecting a `module' program; got userruntime.rkt [,bt for context]
;; or
(make-module-evaluator 'userruntime) ; make-module-evaluator: expecting a `module' program; got userruntime[,bt for context]
How do I refer to the module in the file correctly? Thanks in advance.
If the
module-declarguments tomake-module-evaluatorare strings, they're treated as the code to evaluate. You have to pass a path to have it treated as a file to read from (Or an open input port ( Personally, I findmake-evaluatoreasier to work with, but it has the same requirements for itsinput-programarguments.)Also, your
script.rkthas an infinite loop in its function definitions, you shouldn't useeq?to compare numbers, and the evaluated code doesn't have its toplevel values printed out the way the REPL does - better to wrap the code in a function and call that.With this
userruntime.rkt:and this fixed
script.rkt:this code works:
Since
make-module-evaluatorrequires a module to load, not arbitrary code, one way to use it would be to changescript.rktto:after which
will work.