On Nov 20, 2007 3:19 AM, Neil Toronto <[EMAIL PROTECTED]> wrote:
> Alan Manuel Gloria wrote:
> > On Nov 19, 2007 11:03 AM, Neil Toronto <[EMAIL PROTECTED]> wrote:
> >> I've been following these proposals, and been having a difficult time
> >> keeping the decorations straight. My first reaction was "huh?" followed
> >> by "oh!" and then "why?" I'm not going to claim to be the brightest bulb
> >> in the universe, but I have dabbled in quite a few languages in my quest
> >> for The Perfect Fit, and this confuses me more than most confusing
> >> things I've seen so far.
> >>  - snip -
> >> In my no-longer-professional opinion, you should leave the decorations
> >> to the s-expressions.
> > Hmm.  "decorations" being...?  From my point of view s-exprs hardly
> > have decorations at all - list limits are all started and ended by ( )
> > pairs.
>
> Sorry about that. "Decorations" == delimiting parsing rules using (), []
> and {} enclosures.
So what you mean is, decorations would be used only to say "this is s-expr"?

>
> >> Give the sweet-expression folks One Way to Do It,
> >> which is the full sweet suite, of course. Give them a quick way to drop
> >> down to pure s-expressions if they need to. (Enclosing a list in {}
> >> might work nicely. ;))
> > maybe a tag with () would do better -
> > define somefunction(x y)
> >    if somethingorother(x)
> >        ournewcode(y)
> >        #|Legacy code from old version of somefunction()|#
> >        #s-expr(oldcode (somemoreoldcode x) (lessoldcode y))
> > ...or maybe not.  Hmm.
>
> I thought about that, too. Whether it's good would depend on how often
> sweet-expr people are expected to drop down to pure s-expressions. I
> think the tag would have to be long because any short ones would have
> the potential to collide with a real identifier. Maybe it's not an
> issue, though, if the tag means nothing within real s-exprs.
>
> >> If anyone will want to selectively enable
> >> language features, it won't be these people.
> > I might like to have sweet-exprs, but use some language features too.
>
> Do you mean programming with s-exprs in general, but including
> sweet-expr features when you want them? If you do mean that, which
> subset? I imagine just infix, since syntactic whitespace wouldn't make
> much sense, and function prefixes are very un-s-expr (though potentially
> the easiest to disambiguate without special delimiters, I think).
Or the reverse if feasible, actually - programming in swt-expr but
dropping down to s-expr.

> > Finally - conventional wisdom claims that LISP's most important power,
> > macros, is possible only because of the sheer number of parens in the
> > s-expr syntax (I would contend this, though).  So, just in case macros
> > really, really need s-expr - better keep it in, since we don't want to
> > accidentally cut LISP's power.
>
> I've read this in a few places, but never seen any concrete reason that
> macros can't work with m-exprs. It usually comes down to "if you
> understand macros, you'll already know why" - a type of answer I find
> both maddening and unfortunately common. So... could you very sweetly
> attempt to explain to a non-Lisper exactly why this might be? :)
>
> I'm not attempting to argue the banishment of s-exprs, by the way. I
> just want to understand why people think what they do.
Mind you, I also contend that s-exprs are not *completely* necessary.
However I must also add that in the office we use a proprietary
lisplike called Skill, which supports a subset of m-expr and the full
s-expr (the limitation of the m-expr is that you can't use something
like y = (x) to mean the value of x, as would be valid in C for
example).  I mostly used the m-expr syntax at first.  After I figured
out macros, however, I found myself switching over to s-exprs!

Okay, suppose I introduce to you a hypothetical language called
Stutter.  It's a full m-expr language.  Function calls have the syntax
f[x], math quite sensibly uses a + b * c notation, etc.  The only
weird thing is that assigning a variable uses the set special form -
set[x 42] - because of some weird stuff in the parser that is only
tangentially related to our discussion.

Now I'll introduce to you a special syntax in Stutter.  In Stutter, ()
introduces a data constant called an array, which is just like any
other sequential data collection in any other language.  So it's
possible to do something like this in Stutter:
set[var  (1 2 3 4)]

Stutter is a dynamically-typed language, and arrays can contain
strings, numbers, or even arrays:
set[var (1 "hello" ("sub-array" 4 ))]

Let me introduce to you something new about Stutter.  In Stutter,
variable names are themselves data types.  Let's call them labels
(this is slightly related to why we have a set[] special form).  And
like any other data type, they can be kept in arrays:
set[var (hello world)]

Remember that () introduces an array *constant*.  So (hello world)
will be an array of two labels, hello and world.  It won't suddenly
become (42 54) or anything else even if hello is 42 and world is 54.
The variable's name is a label, but the label is not the variable (at
least not in the array syntax; it was a bit of a bug in the original
implementation, but some guys went and made code that used labels in
that manner and it got stuck in the language spec).

The array is just like any other array in any other language.  You can
concatenate them like so:
set[var append[(array 1) (array 2)]]
=> now var is (array 1 array 2)
You can add an element in front of it like so:
set[var cons[1 (some array)] ]
=> now var is (1 some array)
Array access syntax is not very nice, but it does exist:
nth[1 (this is the array)]
=> this returns the label "is"
You could create an empty array with:
nil[]
And you could create an array with a single element with:
array["hello"]
=> returns the array ("hello")


Oh, and remember those guys who abused the labels in array syntax I
told you about?  Well, they created a sort-of Stutter interpreter, in
Stutter.  However, they sucked at parsing, so instead of accepting
files or strings or stuff like that, their Stutter interpreter
accepted arrays.  They were going to make the parser later, but they
just really sucked at parsing.

They called their Stutter interpreter "lave", because they were hippie
wannabes and were tripping at the time they were choosing the name.
It was supposed to be "love", but like I said, they were tripping.

Of course, since lave accepted arrays, it couldn't get at the nice
f[x] syntax.  So they decided that the first element of an array would
be the function name as a label.  f[x] would become the array (f x).

lave had some limitations.  For example, instead of Stutter's nice
infix syntax a + b, lave needed (plus a b).  Fortunately lave included
a plus[x y] function which was simply:
define plus[x y]
  x + y

So how come these guys became so influential?  You see, Stutter's BDFL
is a bit of a lazy guy.  He is so lazy that he didn't even bother to
fix up the syntax for if-then-else.  In fact, there *was* no
if-then-else.  What was in fact present was a ridiculously ugly cond
syntax:
cond[
   { x == y
        ...your then code...
   }
   { !(x == y) ;yes, what can I say, Stutter's BDFL is lazy
        ...your else code...
   }
]

lave's creators pointed out that you could in fact represent the above
code, in lave-interpretable arrays, as:
(cond
   ( (eq x y)
     ...your then code...)
   ( (not (eq x y))
     ...your else code...))

Then they created a new Stutter function which would accept 3 arrays, like so:
if[
   (eq x y)
   (...your then code...)
   (...your else code...)]
And then it would return the cond array above.

It looked like this:
define if[c then else]
    append[
       (cond)
       cons[c
         array[then]]
       cons[ append[(not) array[c] ]
          array[else]]]

You could then use an if-then-else syntax like this:
lave[
   if[ (eq x y)
        (...your then code...)
        (...your else code...)
    ]
]

Then they thought, hmm, maybe we can integrate this into our lave
function.  So they wisely decided to create a new feature in lave,
called "orcam".  I think it was supposed to be "okra", but
unfortunately I asked them about it while they were tripping, so maybe
I just got confused.

Basically, you could tell lave that certain Stutter functions would be
treated specially in their lave-syntax.  These functions would have
the "orcam" property set in some private data of lave.  Instead of
just running the function, lave would extract the array components,
pass them to the function, and *then* run whatever array that function
returned.  So you could simply say:
lave_set_orcam_property[(if)]
lave[
  (if (eq x y)
     (...your then code...)
     (...your else code...)
  )
]

Because of this, people started creating all sorts of
orcam-property-functions.  For example, there was only a while loop in
the language (lazy, lazy).  Someone created an orcam-property-function
called for:
define for[s c u code]
   append[ (begin) //begin{} is just a compound statement
       cons[ s
           append[(while)
               cons[c
                   cons[ code array[u]]
               ]
           ]
       ]
   ]

So you could do:
for[(set i 0) (less i 42) (preincrement i)
   (begin (print i))]
And it would look like:
(begin
   (set i 0)
   (while (less i 42)
      (begin (print i))
      (preincrement i)
   )
)

So if you wanted something like a C for loop you could do:
lave_set_orcam_property[(for)]
lave[
   (for (set i 0) (less i 42) (preincrement i)
       (begin
            (print i)
       )
   )
]

It was particularly difficult to create nice orcam-property-functions,
but it was easier than trying to get Stutter's BDFL to move.

Soon after lave's creators added orcam-property-functions, Stutter's
BDFL decided to do something about the language.  He was always
bothered about the bug in Stutter array syntax where something like
(hello world) would return, well, the array (hello world), instead of
sensibly returning an array with the values of hello and world.  So he
introduced the `, syntax.  An array constant prefixed with "`" would
have a special meaning.  It would not be completely a constant.
Instead, when it saw a "," Stutter would evaluate the expression
following the comma and insert that element into the array being
created.  So `(,hello ,world) could now become (42 54), if hello was
42 and world was 54.

Some of the top ocam-property-function writers realized that Stutter's
new `, syntax would really, really help.  For example, instead of the
kludgy, virtually unreadable if code, you could just write:
define if[c then else]
  `(cond
       (,c ,then)
       ((not ,c) ,else)
   )
And you could also define for as:
define for[s c u code]
    `(begin
         ,s
         (while ,c
             ,code
             ,u
         )
     )
However, you weren't limited to just the `, syntax.  It was usually
the best choice, but if there was a lave-expression array you wanted
that couldn't exactly be given by "`,", you could still use the good
old append[] and cons[] functions.  In fact, for really complex
lave-expression arrays, a combination of the new `, syntax and the old
append[] and cons[] functions would do quite well.

Because of this, creating orcam-property-functions became easier and
their power skyrocketed.  Other languages which automatically
evaluated variable labels in their arrays couldn't imitate it (so what
was originally a bug - that (hello world) did not evaluate the
variables hello and world - became a feature).  Worse, those other
languages' arrays sometimes couldn't themselves contain arrays, or
even have different types.

Their arrays just weren't powerful enough to hold code, so other
languages never managed to create a powerful orcam-property syntax.

Eventually, people were writing Stutter programs like so:
lave[
  (define (fn x)
     (if (less x 1)
         1
         (times x (fn (minus x 1)))
     )
  )
]

And so, Stutter's BDFL decided to be even more lazy and simply wrote Stutter as:
while[true]{
   print[ lave[ read[] ] ]
}
so that everyone didn't have to keep writing "lave[]"

Sincerely,
AmkG

Reply via email to