Saturday, October 8, 2011

Running a limited REPL in Racket

Let's say you want to only expose some functionality to a REPL and you're using Racket.  One way to do this is to create a module with the functionality you want to expose and then create a namespace that only includes this functionality.

modlang.rkt:


(module um racket
  (provide x doit #%module-begin #%app #%datum)
  (define x 100)
  (define (doit a) (display (+ a 1))))

use_modlang.rkt:


#lang racket


(define ns (make-base-empty-namespace))
(define (ns-req e ns) (parameterize ([current-namespace ns]) (namespace-require e) ns))
(ns-req "modlang.rkt" ns)


(define (prompt-user)
  (printf "prompt> ")
  (define input-string (read-line (current-input-port)))
  (cond 
    [(not (string=? input-string "quit"))
     (printf "~a\n" (eval (read (open-input-string input-string)) ns))
     (prompt-user)]))


(prompt-user)

And now you can run use_modlang.rkt.  At the prompt you can only do simple numerics, x, and the doit function, but even + isn't available.