1.10 S-Expressions
If we write (+ pi pi), then given our earlier definition of pi, the result is as you’d expect:
> (+ pi pi) - Number
6.28
We could add a ' to the front of that expression and get a
completely different result—
> '(+ pi pi) - (Listof Symbol)
'(+ pi pi)
If you’re studying programming languages and building interpreters, this looks like a handy coincidence. You can represent an expression as a list! Unfortunately, this trick does not always work:
> '(+ 1 2) eval:192:0: typecheck failed: Symbol vs. Number
sources:
(quote (+ 1 2))
+
1
A list cannot contain a mixture of numbers and symbols, so it cannot directly represent the expression (+ 1 2).
If you’ve had some experience programming in Java, you might think that the solution is a list of Objects, because anything can be coerced to and from the type Object. That is, we would be able to mix a symbol as Object with two numbers as Objects.
Plait doesn’t have an Object type, but it does have an S-Exp type, which is similar. Even better, the S-Exp type works with a convenient '-like shortcut. The S-Exp shortcut is ` (usually pronounced “backquote”) instead of ':
> `(+ 1 2) - S-Exp
`(+ 1 2)
When an S-expression is list-like, then you can corece the S-expression to a list using s-exp->list. The result is a list of S-Exps:
> (s-exp->list `(+ 1 2)) - (Listof S-Exp)
(list `+ `1 `2)
If an S-expression isn’t list-like, the coercion fails. Other coercions include s-exp->number and s-exp->symbol. You can go the other way with number->s-exp, symbol->s-exp, and list->s-exp. Functions like s-exp-list? and s-exp-number? report whether an S-expression is list-like or number-like.
> `1 - S-Exp
`1
> (s-exp->list `1) - (Listof S-Exp)
s-exp->list: not a list: `1
> (s-exp->number `1) - Number
1
> (number->s-exp 1) - S-Exp
`1
> (list->s-exp (list (symbol->s-exp '+) (number->s-exp 1) (number->s-exp 2))) - S-Exp
`(+ 1 2)
> (s-exp-number? `1) - Boolean
#t
> (s-exp-list? `1) - Boolean
#f
The backquote ` versus forward quote ' distinction is subtle. A convention to help highlight the difference is to mostly use curly braces with `. Curly braces are interchangable with parentheses and square brackets, and Plait won’t print results with curly braces, but the visual cue can still help when reading programs.
> `{+ 1 2} - S-Exp
`(+ 1 2)
> `{* 3 {+ 4 x}} - S-Exp
`(* 3 (+ 4 x))
The S-expression ` has an extra feature that the list-constructing ' lacks: a way to escape back to the evaluated-expression world by using , (i.e., a comma). The escaped expression must produce a S-expression, and the result S-expression takes the place of the escape:
> `{+ 1 ,(number->s-exp (+ 3 4))} - S-Exp
`(+ 1 7)
The ,@ escape form is similar to ,, but ,@ is a splicing escape that expects a list of S-expressions and inlines the elements into the enclosing list-like S-expression.
> `{+ ,@(list (number->s-exp 1) (number->s-exp (+ 3 4)))} - S-Exp
`(+ 1 7)
> `{+ ,(list->s-exp (list (number->s-exp 1) (number->s-exp (+ 3 4))))} - S-Exp
`(+ (1 7))