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—a list of symbols:

> '(+ 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))