Subject: Re: sweet-expressions instead of s-expressions?
From: rpw3@rpw3.org (Rob Warnock)
Date: Sat, 23 Sep 2006 23:19:25 -0500
Newsgroups: comp.lang.lisp
Message-ID: <haednUzCwZrQmovYnZ2dnUVZ_tqdnZ2d@speakeasy.net>
Pascal Costanza  <pc@p-cos.net> wrote:
+---------------
| Neil Toronto wrote:
| > http://www.dwheeler.com/readable/readable-s-expressions.html
| > My main question is whether there are any downsides at all to this
| > approach.
| 
| I don't think so. Adding a surface syntax to Lisp shouldn't be that
| much of a problem, as long as the internal representation stays the
| same. It could indeed be interesting if there were several different
| surface syntaxes, for example including graphical ones, which would
| move Lisp towards something like intentional programming.
+---------------

As in ProGraph (q.v.), perhaps?  ;-}

+---------------
| On the other hand, I also think that adding one ore more surface 
| syntaxes doesn't solve a fundamental problem, and I don't expect
| that a considerably large number of Lispers will take up this idea
| because of that. After all, it's _just_ syntax. In other words, there
| aren't any downsides, but there also aren't any essential upsides.
+---------------

Actually, I would say that, based on my experience with alternative
surface syntaxes for Scheme/Lisp [Google for my name and "P'Lite"
or "OPFR"], there *are* downsides for "Lispers", especially for
writing sizeable programs. I myself have abandoned each of the
surface syntaxes I've come up with for *programming*, because
they (1) got in the way, and (2) were *not* as readable when I
came back to the code weeks, months, or years later. Normal Lisp
[or Scheme] code, on the other hand, is "timeless". IMHO.

That said, I continue to advocate the use of a "mild" parentheses-
light surface syntax [OPFR] for *interactive* (command-line style
or REPL-like) use, especially for non-Lisper users, for a variety
of more-or-less dedicated "tool" programs.

The "hwtool" pattern that I seem to keep re-implementing[1] over
and over at each new job is a prime case in point. It seems to be
something of a sweet spot in design/use space, with the following
salient features:

1. When run from the shell without arguments, you get a command-line
   prompt with a REPL; given arguments, the rest of the line is taken
   as a single input command-line, then it exits.

2. The input [either REPL or shell command] is parsed by "OPFR",
   an "Outer-Parentheses-Free Repl" (q.v.). That is, to a first
   approximation [ignoring details like continuation lines],
   OPFR:OPFR-READ takes an input line string, wraps "(" & ")"
   around it, and calls READ-FROM-STRING, then does the usual EVAL,
   print [including multiple values], and loop.

3. To make life easier for Lisp-aware users [including me],
   any input that begins with "(" is assumed to be a CL s-expr,
   and normal CL:READ is called to read it.

4. For hardware debugging [its main use], the usual panoply
   of PEEK, POKE, DUMP, etc., utility functions is provided.

5. To make life easier for non-Lisper users [and for hardware
   debugging], a "0x" readmacro is enabled, and a "~/0x/" FORMAT
   function is provided to ease the writing of register dumps.

6. A large majority of things a user needs to do with the tool
   are pre-defined as functions, which therefore appear to the
   naive user as "commands" in the REPL.

7. The program sets a fairly large number of global lexical[1]
   convenience variables with values precomputed from the run-time
   environment, so that most of the time all of the "command"
   arguments a user needs are either one of the precomputed
   convenience variables or literal constants. This sharply
   lessens the need for typing actual Lisp arithmetic expressions
   as input.

A very small example:

    $ hwtool
    Hardware debug tool (CMUCL version)
    Warning: Non-root can't mmap "/dev/mem"
    hwtool> loop for i below 10 collect i

    (0 1 2 3 4 5 6 7 8 9)
    hwtool> deflex vec (vector 1 2 3 4 5)

    VEC
    hwtool> d32 vec
    0x48a0b908: 0x00000032 0x00000014 0x00000004 0x00000008
    0x48a0b918: 0x0000000c 0x00000010 0x00000014 0x00000000
    0x48a0b928: 0x48a08b3f 0x48a0b933 0x28f0000b 0x28f0000b
    0x48a0b938: 0x0000008c 0x28f0000b 0x48a0b93b 0x48a08d2b
    hwtool> 

Since I don't have any poke-able hardware registers handy at
the moment, let's reach in and mess with the internals of VEC.
[Don't try this at home unless you and your GC are best of friends!]

    hwtool> w32 0x48a0b918 0x28  ; Decimal 10, as a CMUCL fixnum
    hwtool> d32 vec
    0x48a0b908: 0x00000032 0x00000014 0x00000004 0x00000008
    0x48a0b918: 0x00000028 0x00000010 0x00000014 0x00000000
    0x48a0b928: 0x48a08b3f 0x48a0b933 0x28f0000b 0x28f0000b
    0x48a0b938: 0x0000008c 0x28f0000b 0x48a0b93b 0x48a08d2b
    hwtool> vec

    #(1 2 10 4 5)
    hwtool> w32 0x48a0b920 (lisp-obj #\A)  ; Chars are immeds.

    hwtool> d32 vec
    0x48a0b908: 0x00000032 0x00000014 0x00000004 0x00000008
    0x48a0b918: 0x00000028 0x00000010 0x000041a6 0x00000041
    0x48a0b928: 0x48a08b3f 0x48a0b933 0x28f0000b 0x28f0000b
    0x48a0b938: 0x0000008c 0x28f0000b 0x48a0b93b 0x48a08d2b
    hwtool> vec

    #(1 2 10 4 #\A)
    hwtool> 

As I have written before, this appears to be just enough masking
of the "Lispiness" to make such programs be quite acceptable to
general technical users (e.g., hardware engineers, C programmers).


-Rob

[1] Re-inventing, to avoid IP contamination from the PPoE.

[2] Using the now-common DEFINE-SYMBOL-MACRO hack.

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