[plt-scheme] a tiny repl

From: Ryan Culpepper (ryanc at ccs.neu.edu)
Date: Sun Jun 28 18:43:46 EDT 2009

Hugh Myers wrote:
> On the off chance that others who read this list are as needy as
> myself, what follows is a tiny repl. I use an expanded version to test
> and debug my current work--- single stepping through a chess game for
> instance. Since I'm new to scheme, I've no knowledge of better ways to
> do this, so feel free to criticize. It paid for itself by being
> helpful to me, gravy if helpful to someone else...

I try to stay away from 'eval' unless I really need it. You could 
instead just keep a table of command names and the procedures that 
implement them. Here's how to do it:

   ;; repl : string -> (loops)
   (define (repl prompt)
     (display prompt)
     (let* ([line (read-line)]
            [parts (regexp-split #px"\\s" line)])
       (when (pair? parts)
         (let* ([command-part (car parts)]
                [parameter-parts (cdr parts)]
                [command (lookup-command command-part)]
                [parameters (for/list ([part parameter-parts])
                              (string->actual part))])
           (when command
             (apply command parameters))))
       (repl prompt)))

   ;; lookup-command : string -> procedure/#f
   ;; Gets the procedure that implements the given command,
   ;; or #f if given an unknown command name.
   (define (lookup-command command-name)
     ;; commands : (listof (cons string procedure))
     ;; You can lift this to top-level, but you must put it *after*
     ;; the definitions of 'repl-help', 'jmp', and 'print-board'.
     (define commands
       (list (cons "h" repl-help)
             (cons "q" (lambda () (escape 'Bye!)))
             (cons "j" jmp)
             (cons "p" print-board)))
     (let ([entry (assoc command-name commands)])
       (and entry (cdr entry))))

A few of your functions can now go away, and the rest are unchanged:

   (define (repl-help)
     (printf "~a~%" "Commands are h,p, and q.")
     (printf "~a~%" "Where:")
     (printf "~a~%" "       h =s 'help'")
     (printf "~a~%" "       j n =s 'jmp n plys'")
     (printf "~a~%" "       p =s 'print-board'")
     (printf "~a~%" "       q =s 'quit'"))

   (define (jmp n)
     (printf "jump forward ~A ply in movelist~%" n))

   (define (print-board)
     (printf "display board~%"))

   (define (escape v)
      (lambda () v)))

   (define (string->actual s)
     (let ([value (if (string->number s)
                      (string->number s)
                      (string->symbol s))])

   (define (test-repl)
     (repl "test> "))


Posted on the users mailing list.