[If only] we could find characters or signs suited for expressing all our thoughts as clearly and as exactly as arithmetic expresses numbers... - Gottfried Wilhelm Leibniz, 1677.

"A language should be designed in terms of an abstract syntax and it
should have perhaps, several forms of concrete syntax: one which is
easy to write and maybe quite abbreviated; another which is good to
look at and maybe quite fancy... and another, which is easy to make
computers manipulate... all should be based on the same abstract syntax...
the abstract syntax is what the theoreticians will use and one or more
of the concrete syntaxes is what the practitioners will use. John McCarthy, creator of Lisp

The Problem

Many people find Lisp s-expressions hard to read as a programming notation.
I've developed Lisp programs for decades, and though I can read s-expressions
well, I remain dissatisfied with their syntactic limitations.
Others, including Lisp luminary Paul Graham, feel the same way.
(
Tim Bray loves Clojure, but not its syntax.)
Yet s-expressions have a lot of benefits to them, and it turns out
to be very hard to design a more readable notation
that retains all the benefits of s-expressions.
But I believe it is possible - so let's try!

This web page identifies some ways to extend/modify
s-expressions so they can be more readable without losing their power
(such as homoiconicity, generality, macros, quasiquoting,
and easily-manipulated program fragments).
A vast number of projects have tried to create "a more readable
Lisp notation" and failed, including M-expressions, IACL2, and Dylan.
In hindsight, it's clear that they failed because they didn't have some
key advantages of S-expressions, in particular, that they are generic
(they do not depend on some underlying semantic)
and homoiconic (the underlying data structure is clear from the syntax).
Since these old "readable Lisp" syntaxes weren't generic or homoiconic,
they could not handle semantic change and metaprogramming - yet
those are some of the very reasons someone would use a Lisp!
Now that we know why those efforts failed, we can avoid their mistakes.

My goal is to spur work to create one or more readable, general-purpose,
homoiconic notations for s-expressions that do a good job representing
programs. A good way to measure that is to see that it should be easy
to translate back and forth between arbitrary S-expressions and this other
notation (by computer and in people’s heads).

If you are unwilling to consider that there might be a better approach,
read my retort/rebuttal that
Lisp can be readable.
If you're still unwilling to consider alternatives, stop reading.
But if you're interested in developing a better way, keep reading.
After all, the quote operator ' did not fall from the sky - it was not
in the original Lisps, and was added because that construct was so
common that it was worth creating an abbreviation.
We're just adding new abbreviations.
On this page, I explain how to get involved, present my 3-layer approach
(curly infix, modern-expressions, and sweet-expressions),
and point to others' approaches to the problem.

Sweet-expressions: Includes modern-expressions, and adds the idea that
indentation is meaningful (like Python, Haskell, and many other languages).

All of these can be used in any Lisp-like language
(Common Lisp, Scheme, Emacs Lisp, ACL2, BitC,
CLIPS, etc.).
Curly-infix is 100% compatible with existing code; modern-expressions
and sweet-expressions are 100% compatible with well-formatted code.

Sweet-Expression Examples

Let's do two quick examples - we'll use sweet-expressions version 0.2
to represent calculating factorials and Fibonacci numbers,
in both cases using Scheme:

Note that you can use traditional math notation
for functions;
fibfast(n) maps to (fibfast n).
Infix processing is marked with {...};
{n <= 2} maps to (<= n 2), and
f{n * 2} maps to (f (* n 2)).
Indentation is significant, unless disabled by (...), [...], or {...}.
This example uses variable names with embedded "-" characters; that's
not a problem, because the infix operators must be surrounded by whitespace
and are only used when {...} requests them.

It's actually quite common to have a function call pass one parameter,
where the parameter is calculated using infix notation.
Thus, there's a rule to simplify this common case (the prefix {} rule).
So factorial{n - 1} maps to
factorial({n - 1}) which maps to
(factorial (- n 1)).

From the SourceForge page (noted above) you can download implementations.
There's a production-ready Common Lisp implementation of curly infix,
and a reasonably complete (though work is still ongoing) Scheme implementation
of Sweet-expressions.

Analysis of alternatives

If you want even more detail, look here:

The Sweet-expressions version 0.2 page
shows examples and experimentation that led to sweet-expressions
version 0.2, including the split into three layers and removing
automatic determination of infix operators.
The latter was a surprise; I thought automatically determining infix would
be a big advantage, but the experiments suggested otherwise.
It shows sweet-expressions using samples of many different
Lisp-based languages - this shows that sweet-expressions are not
tied to a particular semantic.

My older paper
"Readable s-expressions and sweet-expressions: Getting the infix fix and fewer parentheses in Lisp-like languages"
has lots more information.
It's the original paper I used to
identify and discuss various ways to make s-expressions to read.
It identifies three approaches that seem particularly promising:
indentation, name-prefixing (so func(x y) is the same as (func x y)),
and infix support.
In the process of creating sweet-expressions, I went through many
alternatives, and wrote down in this paper what I learned as I went.
It turns out that many people have tried to solve this problem but foundered;
I think by learning from their problems I've got a better mousetrap.
You may find my thoughts helpful!
This resulted in the development of sweet-expressions version 0.1.

Implementation approaches

I want to have final sweet-expression readers that
work on Scheme, Common Lisp, emacs Lisp, and ACL2 at least,
without having to implement it multiple times.
Scheme is in some ways the most strict of the these,
e.g., it's picky about the meaning of a boolean value,
what is at the end of a list, and the legal names of parameters.
Thus, I've been implementing sweet-expressions in
a small subset of "easily translatable"
Scheme, so that it can eventually be auto-translated to other Lisps.
(It's easier to translate from more-picky Scheme to others than vice-versa.)
ACL2 has a very short list of built-ins, which are
similar to Scheme's, so this seems plausible.
Perhaps I could use
Dorai Sitaram's
Scmxlate Scheme translate tool (LGPL license) so that I could write
a single implementation and have it be useful in Common Lisp (CL) and ACL2
as well.
The final program will be so small
that a specialized program to do the translation might be enough.

Ideally, an implementation should go both ways
(translate text to S-expressions, and
pretty-print S-expressions as indented with infix format).
It should be absolutely rock-solid (maybe even proved).
It should also provide a "check for change" tool, e.g., read in some
text using the 'regular' read and the indented, and make sure there's
no change.

Why am I bothering?

I'm very interested in improving the security and safety of programs.
Doing that well requires good program analysis tools.
S-expressions have proven themselves, over many decades,
to be a very good tool for creating programs to
transform or analyze programs (or other symbolic systems).
Many proving tools such as ACL2 and PVS are based on s-expressions,
as well as existing computer alegebra tools like
Axiom and
Maxima.

Sadly, traditional s-expressions are nearly unreadable to most people,
making them difficult to use, and a notoriously poor way to communicate
with a wider world.
Its inability to properly support infix notation directly -
a basic starting point for symbolic manipulation of mathematics -
is laughable in the 2000s.
By having a readable notation for s-expressions, I hope to be able to
spur on better abilities for programs that analyze programs... resulting
(perhaps) in more secure and safe programs.

Besides, I'm drawn like a moth to the flame of "impossible" problems.
For more proof of this character flaw, see my
trusting trust
web page.

SRFI-49,
I-expressions
are an alternative method for presenting s-expressions
(either program or data), using indentation.
I-expressions have no special cases for semantic constructs of the language.
SRFI 49 includes a sample implementation with an MIT-style license.

Infpre is
A Common Lisp infix utility (LGPL license).
It converts between prefix and infix.
"The intended use is for CL programs with long math formulas", and it
contains the functions "infix->prefix" and "prefix->infix", as well
as the macros "math" and "!!". It supports precedence.

Guile's ice-9 infix module.
Infix expressions are surrounded by #[...]; precedence, infix, and
prefix functions are supported (though you must declare each one before use);
name-prefixed functions are used with comma-separated parameters.
However, you can't mix ordinary Lisp code inside them (e.g., there
doesn't seem to be support for quasiquotations); it switches to
a completely different and incompatible language inside.