
S-expressions - fogus
https://igor.io/2012/12/06/sexpr.html
======
manaskarekar
A highly recommended read from defmacro.

<http://www.defmacro.org/ramblings/lisp.html>

Other articles on the site are very nice as well: <http://www.defmacro.org/>

~~~
ScottBurson
Yes, it is a great article, but it saddens me that we have to invoke XML to
explain S-expressions rather than the other way around. S-expressions have
been around since 1958! They are maybe the best reason that everyone should
learn Lisp even if they don't wind up using it much, just so they know there
are problems it already solved long ago, and they don't need to reinvent the
wheel.

------
octo_t
Parsing S-expressions is easy: Dijkstra solved it in a really nice way with
the Shunting Yard Algorithm.

~~~
slurgfest
Thank you for this post, because it made me curious enough to look up
Dijkstra's views on LISP. (It seems he credited it for some innovations but
had a lot of complaints about its early design and docs, and favored ALGOL
family design decisions)

------
brudgers
_"Stay tuned for follow-up posts."_

For those interested, there was follow-through on the promise to follow-up:

<https://igor.io/>

~~~
sea6ear
The follow-up posts look really interesting.

Looks like they go through the complete implementation of a lisp system
including macros using PHP as the host language.

------
splawn
Was the use of dict and list necessary? This is an actual question, not a
rhetorical criticism. I have recently been trying to learn common lisp.

~~~
rdtsc
It is if you want to differentiate between a list of lists and a map. Maps are
not natively supported in s-expressions.

So there is a need to create a sub-language to handle special data structures.

I have done this as well. But I use a special namespace '#dict' for example.
So it would be

    
    
        (#dict (k1 v1) (k2 v2))
    

This way there is less of a chance of collision between data and this sub-
language. It also allows for extension, so for example instead of dict you can
use #classname to say persist a perticular object of a given class name (json
doesn't allow this, there would have to add a '__classname__' key to the
object for example.

Another way of doing it is using a flat list and just using an alternation
with keys being prefixed by some special character:

    
    
       (:k1 v1 :k2 v2)
    

I think Clojure and some lisps do that...

~~~
pnathan
That's an nice idea, using #<datastructure> as a straight-up constructor. I've
always found hash-tables to be a colossal pain to create in Common Lisp. I
tried to create a special JSON-esque syntax in CL for them, but it wasn't a
smooth semantic drop-in.

~~~
rdtsc
Yeah I think it is pretty neat too. I had a couple of design ideas. This way I
can persist some other structures (from Python for ex):

For set():

    
    
       (#set v1 v2 ...)
    
     

For circular object graphs, I can encode an object reference to avoid
serializing the same object twice:

    
    
       (#ref oid)
    

Then of course there are custom class names I can pass in to serializer and
deserializer:

    
    
        (#MyClass (attr1 val1) (attr2 val2) ...)
    
    

This might not map to all languages but it worked for me.

~~~
pnathan
CL uses # as a special character; I rewrote the idea into the (CL-standard
idiom) `make-map` nomenclature: <https://gist.github.com/4709844>

But yea, I hadn't thought of particularly using this idea. It's a good idea
from Python (or maybe its older than that, IDK). :-)

------
ecmendenhall
> Side note: Wouldn't it be awesome if composer supported composer.sexpr files
> natively, so that we would no longer have to write JSON?

If you, too, think this would be awesome, check out extensible data notation:
<https://github.com/edn-format/edn>.

------
billpg
You could write code in XML and JSON too, you just need to define meanings.

[add][item]1[/item][item]2[/item][/add]

~~~
TeMPOraL
> _You could write code in XML and JSON too_

And many do (e.g. Ant), but doesn't that sadly look like reinventing the
wheel?

------
chimeracoder
> Side note: Wouldn't it be awesome if composer supported composer.sexpr files
> natively, so that we would no longer have to write JSON? No, not really.

Why the quick dismissal? I find s-expressions much easier to work with than
JSON.

~~~
igorw2
Let me clarify the reason for this.

Many people asked for yaml support in composer, and it was shot down. Here's
why: Once you start supporting many formats you lose interoperability, as any
tooling now needs to support all formats. That is the main reason why composer
will not support sexpr.

------
MichaelGG
Why are the keywords written with a quote?

> (keywords '(useless microframework academic swag))

Shouldn't it be a list with strings or something? What if the keywords were
complex structures not just strings?

~~~
RaphiePS
The only Lisp I know is Racket (basically Scheme), so take the following with
a grain of salt.

'(foo bar baz) is _almost_ the same thing as (list foo bar baz). However, '
also makes the contents of the list into symbols, not variable references.
Basically, '(foo bar baz) returns (list 'foo 'bar 'baz), not a list containing
the values of the variables foo, bar, and baz.

Symbols aren't much like strings. They're immutable, and actually just refer
to a unique number, not characters. I hope that sort of makes sense!

~~~
randallsquared
> Symbols aren't much like strings. They're immutable, and actually just refer
> to a unique number, not characters.

Depending on language, that could make them exactly like strings. :)

~~~
derleth
If you have immutable strings and a smart compiler, yes, you could indeed have
strings and symbols that are functionally identical. In fact, in Old Lisp,
there were no strings and symbols were used for everything we use strings for
now; that lead to weak string handling and it's why Common Lisp and all modern
Lisp variants have a string type.

------
mwexler
What's great about this is not only that it's a good quick summary, but it
left me wanting more. That means I actually feel like I was getting somewhere
with it, instead of it being instantly forgotten.

------
lttlrck
Thanks! 30 seconds of reading and I have at least a basic understanding.

------
japaget
Near the front of the main article is "(sexpr lexer reader eval forms special-
forms macros walker)". Each word in the above parenthesized expression links
to another article in the series.

------
informatimago
See also Rivest's Sexps: <http://people.csail.mit.edu/rivest/Sexp.txt>

------
juan_juarez
> I want to know how to parse them in PHP.

Step one : Stop using PHP.

------
jhrobert
If you love the expressiveness of S-expressions but hate the super noisy
parenthesis, check the sugar version, called "sweet-expressions".
<http://readable.sourceforge.net/>

~~~
chc
I find that alternative syntaxes like this for S-expressions tend to get
really awkward when confronted with real-world Lisp code. For example, the
following code sample†:

    
    
      (define (pointless-function a z)
        (let* ((numbers (map (lambda (n) (* n 2)) (range a z)))
               (multiple-of-three? (lambda (n) (= 0 (mod n 3))))
               (multiples-of-three (filter multiple-of-three? numbers)))
          (printf "Your numbers are: ~s~%" multiples-of-three)))
    

AFAIK, this code only gets noisier when you introduce a paren-free syntax, as
you need to introduce hacks to get around the simultaneous necessity and lack
of parentheses.

† _OK, I'll grant you, this function is not at all realistic. But I think the
structure of the code is pretty lifelike. I didn't have any Lisp code at hand
to use as an example, so I just banged out something that used let and lambda
to illustrate that the structure of S-expressions can be pretty intricate._

~~~
qu4z-2
My ideal s-expression syntax would allow you to replace some brackets with
whitespace. For instance, your function would become:

    
    
      define (pointless-function a z)
        let*
            numbers (map (lambda (n) (* n 2)) (range a z))
            multiple-of-three? (lambda (n) (= 0 (mod n 3)))
            multiples-of-three (filter multiple-of-three? numbers)
          printf "Your numbers are: ~s~%" multiples-of-three
    

Obviously there are some down-sides, but the main idea is that the mapping
should have no knowledge of the language details, and be a pure s-expression
transform. I really should explore the idea more. I have no idea whether the
above example can even be uniquely parsed.

