Readable s-expressions
(let
((a 1)
(b 2))
(message
(number-to-string
(* (- a b) (+ a b)))))
“I’ve used Lisp my whole programming life and I still don’t find prefix math expressions natural.”
- Paul Graham
“Lisp has all the visual appeal of oatmeal with fingernail clippings mixed in.”
- Larry Wall
“After 13 years of doing Lisp and 3 or 4 years of Python, I agree: I prefer writing Lisp, but Python is easier to read.”
- John Wiseman
useful regardless of underlying semantic underlying data structure is clear from the syntax“LISP: … ‘Lots of Irritating Superfluous Parentheses’”
- Jargon File
'x means (quote x)
(a b c) means (a . (b . (c . ())))
“When you program, you spend more time reading code than writing it… a language that makes source code ugly is maddening to an exacting programmer, as clay full of lumps would be to a sculptor.”
- Paul Graham
Normally-formatted s-expressions keep working
(let
((a 1)
(b 2))
(message
(number-to-string
(* (- a b) (+ a b)))))
(let
((a 1)
(b 2))
(message
(number-to-string
{{a - b} * {a + b}})))
let((a(1)
b(2))
message(
number-to-string(
{{a - b} * {a + b}})))
let
\\
a 1
b 2
message
number-to-string
{{a - b} * {a + b}}
(c-expressions)
- S-expressions, + curly braces \{…\} contain an “infix list”
- A “simple infix list” represents one operation; it has:
- An odd number of parameters
- At least 3 parameters, and
- All even parameters are the same symbol … maps to “(even-param odd-params)” so \{2 + 3\} maps to (+ 2 3)
- Otherwise maps to “(nfx parameters)”.
- No built-in precedence, use another \{…\} for embedded list
{n <= 2} ↓ (<= n 2)
{2 * 3 * 4} ↓ (* 2 3 4)
{2 + {3 * 4}} ↓ (+ 2 (* 3 4))
{2 + 3 * 4} ↓ (nfx 2 + 3 * 4)
- e(…) → (e …)
- e\{…\} → e(\{…\})
- e[…] → (bracketaccess e …)
- unprefixed “( . e)” → e
f(1 2) maps to (f 1 2)
f{n - 1} maps to f({n - 1}) which maps to (f (- n 1))
- Includes neoteric-expressions, and deduces parentheses from indentation
- An indented line is a parameter of its parent
- Later terms on a line are parameters of the first term
- A line with exactly one term, and no child lines, is that term; multiple terms are wrapped into a list
- An empty line ends the expression
- Empty lines before expressions are ignored
- No indentation processing inside ( ), [ ], and { }
- Stop “Lots of Irritating Superfluous Parentheses”
define factorial(n)
if {n <= 1}
1
{n * factorial{n - 1}}
(define (factorial n)
(if (<= n 1)
1
(* n (factorial (- n 1)))))
define long-and-boring?(x)
cond
not(pair?(x)) #f
not(list?(x)) #f
{length(x) < boring-length} #f
#t boring?(x)
define unit-list(x)
cond
null?(x) '()
pair?(x)
if null?(cdr(x))
unit car(x)
append unit(car(x)) LISTSPACE unit-list(cdr(x))
#t append(LISTSP.SP unit(x))
- ;-comment-only-lines completely ignored
- Even indentation irrelevant
- Useful to “separate” lines without ending whole expression
- Indents: one-or-more space, tab, and/or !
- A line with only indentation is an empty line
- If an expression starts indented, then indentation disabled
- “!” is surprising, but solves past problems with indentation-sensitive syntaxes & enables highlighting
- A \text{\textbackslash\textbackslash} between datums (aka SPLIT) starts a new line at current indentation
- A \text{\textbackslash\textbackslash} after indent (aka GROUP) represents no symbol
- Useful for lists of lists
- A $ in the middle of list (aka SUBLIST) restarts list processing (Haskell-like)
- Right-hand-side (including sub-blocks) is the last parameter of left-hand side
- Leading quote (etc.), followed by space or tab, quotes rest
define factorial(n)
if {n <= 1}
1
{n * factorial{n - 1}}
(define (factorial n)
(if (<= n 1)
1
(* n (factorial (- n 1)))))
Can be used in makefiles
Simplifies transition
Can use guile, scsh, clisp, …
“Readable”
- is much more readable
- is easier to understand
- uses three tiers
- Curly-infix-expressions: \{a + b\}
- Neoteric-expressions: f(a b)
- Sweet-expressions: f a b
More info & implementation: readable.sourceforge.net
- This presentation is released under the Creative Commons Attribution 3.0 Unported license (CC BY 3.0)
- You may share, remix, and make commercial use of the work, as long as you give attribution to “David A. Wheeler”.
- creativecommons.org/licenses/by/3.0/