Julian Stecklina <der_julian@web.de> wrote:
+---------------
| "projectshave@yahoo.com" <projectshave@yahoo.com> writes:
| > I'd wager that the lack of a small Lisp environment for writing quick &
| > dirty utilities *might* be a reason. ...
|
| scsh, the scheme shell, is a very nice thing to write utilities in.
| Would be a nice candidate to port to ECL or GCL, though.
+---------------
I agree, Scsh is nice, but... There's a problem with trying to
implement Scsh *exactly* in Common Lisp, namely, in Common Lisp
there is no standard list representation defined for the result
of a READ of the comma or comma-at syntax, nor does Common Lisp
permit comma or comma-at syntax which is not properly nested within
backquote syntax to be read in forms to be evaluated.
In Scheme, on the other hand, backquote, comma, and comma-at are
merely read macros much like quote and sharp-quote in Common Lisp.
That is, each of backquote, comma, and comma-at are *defined*
to produce a specific internal list representation for each,
which can reliably be manipulated by a user-defined tree walker.
To say it another way, in both CL and Scheme [using "==>" here to
mean "is READ as"]:
'a ==> (quote a)
and in CL [though not Scheme]:
#'a ==> (function a)
But in Scheme -- though *NOT* in CL! -- the following all have
similarly-definite READ representations defined:
`a ==> (quasiquote a)
,a ==> (unquote a)
,@a ==> (unquote-splicing a)
That is, the QUASIQUOTE, UNQUOTE, and UNQUOTE-SPLICING symbols are
all special operators when a quasiquoted form is evaluated, but more
importantly, they have defined READ representations as non-evaluated
*data* as well. This means that Scheme macros can contain argument
forms which contains comma or comma-at syntax which is *NOT* properly
nested within backquotes, and also that the macros [and any tree
walkers they contain] can depend on the structure of the READ results.
Why does this matter? Because much of the convenience of Scsh comes
from the fact that a large number of the most-commonly-used macros
in Scsh "implicitly backquote" their arguments. For example, this
is legal Scsh:
(let ((foo "filename"))
(run (ls -l ,foo))) ; Note no backquote before the comma!
That's simply not possible with most CL readers [and certainly not
portable CL in any case].
Yes, for each short macro form there is a longer functional form that
could be made to work in CL, but it's much less succinct. The above
example could be re-written as follows:
(let ((foo "filename"))
(wait (fork (lambda () (exec-path `(ls -l ,foo))))))
Still, it might be possible to come up with CL versions of the "run",
"fork", "pipe", etc. macros that *don't* try to implicitly backquote
their arguments, and which must be given explicitly backquoted args.
That is, the original example could work in CL if it looked liked this:
(let ((foo "filename"))
(cl-run `(ls -l ,foo)))
But this is still not adequate for portability, since different
CL implementation represent the results of reading `(ls -l ,foo)
differently. For example, [if you work *really* hard to peek under
the covers] you will find CLISP gives the following [very much
like the Scheme standard, actually]:
(SYSTEM::BACKQUOTE (LS -L (SYSTEM::UNQUOTE FOO)))
whereas CMUCL gives this:
(LISP::BACKQ-LIST (QUOTE LS) (QUOTE -L) FOO)
Both will give equivalent results when *evaluated* by their
corresponding evaluators, but the unevaluated forms are sufficiently
different to make it "interesting" to implement the full set of
Scsh macros [which need to walk the unevaluated backquoted forms
rewriting them into their equivalent functional forms]. And that's
just two versions of CL...
-Rob
-----
Rob Warnock <rpw3@rpw3.org>
627 26th Avenue <URL:http://rpw3.org/>
San Mateo, CA 94403 (650)572-2607