
S-Expressions (1997) - panic
https://people.csail.mit.edu/rivest/Sexp.txt
======
mitchtbaum
Is it impossible to improve on s-expression notation?

[https://srfi.schemers.org/srfi-110/srfi-110.html#cant-
improv...](https://srfi.schemers.org/srfi-110/srfi-110.html#cant-improve)

~~~
yogthos
The problem with these schemes is that they're at odds with metaprogramming.
One huge advantage of s-expressions is that the code is expressed using data
literals. You can take any piece of code transform it as you would any regular
data and then run it.

The biggest practical improvement that I've seen was Clojure notation that
expands the number of data literals to include vectors, maps, and sets. I
think this greatly helps with readability as it provides additional visual
cues, while still preserving homoiconicity.

~~~
kmill
> The problem with these schemes is that they're at odds with metaprogramming.
> One huge advantage of s-expressions is that the code is expressed using data
> literals.

I don't think it is necessary for there to be a single uniform syntax for code
to be able to fully leverage metaprogramming.

Take for instance Mathematica (barring complexities of the evaluator
itself...) The underlying type for almost everything in the language is the
"expression," essentially a tagged list. The front-end language, called
"standard form," can be converted to and from expressions. Expressions can
more-or-less be directly serialized as "full form," which looks like
McCarthy's M-expressions, and standard form extends this notation with
operators and precedence rules. (Technically, standard form is given in a 2d
graphical notation that is parsed into expressions, and "input form" is linear
text. All the forms are interconvertible.) Programming in Mathematica seems to
amount to writing lots of transformation rules for expressions, and it usually
works out just writing the code you want to match against, but with pattern
variables as holes. You are also free to write in full form for patterns if it
helps make intent more precise.

I think many cases of code transformation involve a pattern to match against.
A language with few syntax classes and with metavariables can support
metaprogramming easily enough. There are a few examples I've seen, and,
although I can't remember the names, I think MetaOCaml was one.

I guess what I'm saying is, so long as you make it so there is a "code
literal," no matter the purported "homoiconicity" properties, you're good for
metaprogramming.

> while still preserving homoiconicity

I think Alan Kay using the word "homoiconic" for Lisp was a mistake. The
syntax of Lisp really is not the same as the internal representation, unlike
the Tcl (which I understand actually executes by manipulating strings). This
is a reason structured editors for Lisp don't seem to work out.

Here is a new word: autoiconic ("self representing"). A language is autoiconic
if there are composable code literals. It is not necessary for an autoiconic
language to have "eval," but it is necessary to be able to read in code and
then write out equivalent code. Furthermore, the code literals must allow for
metavariables and composability: replacing a metavariable with a code literal
must result in syntactically valid code when written. This excludes Javascript
even though it has template literals.

It is questionable whether Clojure is actually homoiconic, but it is arguably
autoiconic since it has quasiquotation. (However, the way the quasiquoter
works, a read/write cycle will result in code with a bunch of list
manipulation functions. The supposed code literal disappears!)

~~~
kazinator
The problem with "homoiconic" is that it is about a storage mechanism: it says
that function definitions are input into the image in a textual format and are
stored in more or less that format so that they can later be recalled and
edited.

"homoiconic" languages can regurgitate their definitions. E.g. the _set_
command in the POSIX shell, or _LIST_ in classic BASIC.

Those features are helpful interactively in that they allow a human to
transform the code right inside the image by recalling, changing and
reinstalling definitions.

In Lisp, a data structure can be regurgited, rather than definitions. That is
helpful in interactively debugging automated, rather than manual
transformations.

Moreover, the data structure is not regurgitated from a homoiconic form. It is
isomorphic to the text in some way so that the data structure can be
visualized from the text easily and vice versa. The programmer writes
transformations which manipulate the data. These transformations take place in
pipeline-like successive steps, where it is useful to intercept the process at
different stages.

The programmer of a homoiconic language doesn't do this; the programmer
manipulates only the text. A BASIC programmer never works with the internal
tokenized lines, for instance, in which a word like PRINT is condensed down to
one byte. There is no access to that representation via any API from the
language.

Homoiconic languages don't place any transformation between the programmer
input of a definition and the definition's storage; to do so would mean not to
be homoiconic!

ANSI Lisp has a very vaguely defined support for homoiconicity: the function
_ed_ which is intended to recall a function definition and allow the
programmer to edit it. This feature is not very prominent; it is not the basis
of Lisp interactivity. Almost every aspect of the function is implementation-
dependent. To support _ed_ , an implementation's _defun_ operator has to store
the un-expanded form somewhere.

~~~
kmill
This is a reasonable characterization of homoiconicity.

Interestingly, by this definition, v8's implementation of Javascript is
homoiconic since functions can be converted to strings, recovering the actual
source text for its definition.

I once took advantage of this to make a Smalltalk-like source editor for
Javascript: [http://tmp.esoteri.casa/grip/](http://tmp.esoteri.casa/grip/)
(things might no longer work since I last was using it four years ago; I
lightly edited it tonight to get it to start up without a file server. Only
tested in Chrome!)

It's based on an class-based object system I made that can serialize all of
its class definitions. This drives both the class browser and the code
serializer/saver.

(Right now it has two code browsers because I was in the process of making a
nicer one. Somehow, I had the idea that I was going to program a whole webapp
with this thing, but I lost motivation.)

------
nfoz
Seems like this definition is tied to US-ASCII and that we'd need another spec
(even if trivial) for any S-expressions that would intend to allow raw
Unicode.

------
chowes
Looks awfully similar to Mark

~~~
brians
Canonical forms seem a big win. And teeny parsers.

~~~
dwheeler
There's always a trade-off. These parsers aren't very large anyway, in part
because they are general (sweet-expressions, like S-expressions, aren't tied
to any particular semantic).

