[plt-scheme] a tiny repl
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)
(abort-current-continuation
(default-continuation-prompt-tag)
(lambda () v)))
(define (string->actual s)
(let ([value (if (string->number s)
(string->number s)
(string->symbol s))])
value))
(define (test-repl)
(repl "test> "))
Ryan