# Write Yourself a Scheme in 48 Hours/Building a REPL

So far, we\'ve been content to evaluate single expressions from the
command line, printing the result and exiting afterwards. This is fine
for a calculator, but isn\'t what most people think of as
\"programming\". We\'d like to be able to define new functions and
variables, and refer to them later. But before we can do this, we need
to build a system that can execute multiple statements without exiting
the program.

Instead of executing a whole program at once, we\'re going to build a
*read-eval-print loop*. This reads in expressions from the console one
at a time and executes them interactively, printing the result after
each expression. Later expressions can reference variables set by
earlier ones (or will be able to, after the next section), letting you
build up libraries of functions.

First, we need to import some additional IO
functions. Add the
following to the top of the program:

``` haskell
import System.IO
```

Next, we define a couple of helper functions to simplify some of our IO
tasks. We\'ll want a function that prints out a string and immediately
flushes the stream; otherwise, output might sit in output buffers and
the user will never see prompts or results.

``` haskell
flushStr :: String -> IO ()
flushStr str = putStr str >> hFlush stdout
```

Then, we create a function that prints out a prompt and reads in a line
of input:

``` haskell
readPrompt :: String -> IO String
readPrompt prompt = flushStr prompt >> getLine
```

Pull the code to parse and evaluate a string and trap the errors out of
main into its own function:

``` haskell
evalString :: String -> IO String
evalString expr = return $ extractValue $ trapError (liftM show $ readExpr expr >>= eval)
```

And write a function that evaluates a string and prints the result:

``` haskell
evalAndPrint :: String -> IO ()
evalAndPrint expr =  evalString expr >>= putStrLn
```

Now it\'s time to tie it all together. We want to read input, perform a
function, and print the output, all in an infinite loop. The built-in
function
`interact`
*almost* does what we want, but doesn\'t loop. If we used the
combination `sequence . repeat . interact`, we\'d get an infinite loop,
but we wouldn\'t be able to break out of it. So we need to roll our own
loop:

``` haskell
until_ :: Monad m => (a -> Bool) -> m a -> (a -> m ()) -> m ()
until_ pred prompt action = do 
   result <- prompt
   if pred result 
      then return ()
      else action result >> until_ pred prompt action
```

The underscore after the name is a typical naming convention in Haskell
for monadic functions that repeat but do not return a value. `until_`
takes a predicate that signals when to stop, an action to perform before
the test, and a function-returning-an-action to do to the input. Each of
the latter two is generalized over *any* monad, not just `IO`. That\'s
why we write their types using the type variable `m`, and include the
type constraint `Monad m =>`.

Note also that we can write recursive actions just as we write recursive
functions.

Now that we have all the machinery in place, we can write our REPL
easily:

``` haskell
runRepl :: IO ()
runRepl = until_ (== "quit") (readPrompt "Lisp>>> ") evalAndPrint
```

And change our main function so it either executes a single expression,
or enters the REPL and continues evaluating expressions until we type
`quit`:

``` haskell
main :: IO ()
main = do args <- getArgs
          case length args of
               0 -> runRepl
               1 -> evalAndPrint $ args !! 0
               _ -> putStrLn "Program takes only 0 or 1 argument"
```

Compile and run the program, and try it out:

`$ ghc -package parsec -fglasgow-exts -o lisp [../code/listing7.hs listing7.hs]`\
`$ ./lisp`\
`Lisp>>> (+ 2 3)`\
`5`\
`Lisp>>> (cons this '())`\
`Unrecognized special form: this`\
`Lisp>>> (cons 2 3)`\
`(2 . 3)`\
`Lisp>>> (cons 'this '())`\
`(this)`\
`Lisp>>> quit`\
`$`

