Subject: Re: best environment for learning Lisp?
From: rpw3@rpw3.org (Rob Warnock)
Date: Tue, 30 Jun 2009 19:29:40 -0500
Newsgroups: comp.lang.lisp
Message-ID: <i7Cdnbqv38dpMNfXnZ2dnUVZ_hqdnZ2d@speakeasy.net>
Giorgos Keramidas  <keramida@ceid.upatras.gr> wrote:
+---------------
| ccc31807 <cartercc@gmail.com> wrote:
| > ... I have figured out how to compile, load, and run a script in SLIME.
| > However, when my script hangs, all I know how to do is kill the
| > process and start a new one, which takes time and frustrates the heck
| > out of me.
| 
| Most of the scripting languages in wide use today favor a sort of
| programming that is a bit un-Lispy, using a repetitive cycle of edit,
| save, run script, stare at debugging output, repeat.  Lisp supports that
| sort of programming too, as you have found out, but you are missing out
| a *lot* of its power if you have to restart every time something odd
| happens.
| 
| Most of the power of having a full Lisp at your user-interaction prompt
| comes from a different sort of programming: an incremental way of ``REPL
| sessions''.  Instead of saving a short script and running Lisp with the
| script as input, you directly enter forms at the REPL prompt and watch
| for ``interesting'' things that happen as you define, redefine, extend
| and experiment with the code already loaded in your Lisp image.
+---------------

It is possible to combine these modes to one's benefit, provided that
you write your "scripts" in a way that cooperates with your development
environment. Simply find *something* that is different when the script is
run standalone versus when you're debugging and LOAD the script into your
Lisp (either a raw REPL or via SLIME or some IDE, etc.). For example, in
my personal environment it's whether or not the keyword :REPL is present
in the list in the global variable EXTENSIONS:*SCRIPT-EXIT-HOOKS*.[1]

So I conventionally write all my scripts to *not* do anything in
top-level forms that is likely to be dangerous or have problems,
but rather just define functions, ending with a (DEFUN MAIN () ...).
Then at the very end of each script, there's this snippet:

    (unless (find :repl ext:*script-exit-hooks*) ; Debugging?
      (main))                                    ; No, just run & exit.

So if one LOADs the script, it does nothing but define variables
[with "safe", idempotent values] and functions. You can then examine
or modify the variables and call the functions and so forth until
the script is thoroughly debugged. It should then execute correctly
when run standalone.

[The environment in your Lisp will require a different test,
but the general principle should apply, mutatis mutandis...]


-Rob

[1] My scripts use the hack I added to CMUCL:

      http://rpw3.org/hacks/lisp/site-switch-script.lisp

    which allows you to run scripts that start like this:

      #!/usr/local/bin/cmucl -script

    The "site-switch-script" code defines a *SCRIPT-EXIT-HOOKS*
    variable that says what to do when the script finishes loading.
    For scripts that simply exit when done, this will be NIL. For
    scripts that want a normal CMUCL REPL to start up after they're
    loaded, *SCRIPT-EXIT-HOOKS* will be a list containing the keyword
    :REPL in it somewhere. My normal REPL-based debug environment
    will have this set [since it's such a script itself!].

-----
Rob Warnock			<rpw3@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607