# Quasiquotation

`QUASIQUOTE` is an extension of the `QUOTE` special form which is convenient for writing macros.

For symbols and other simple data, `QUASIQUOTE` behaves like `QUOTE`, returning the datum unevaluated. Lists are also return without being evaluated, with two exceptions. If an element of the list (or a sub-list) is of the form `(UNQUOTE expr)`, then `expr` is evaluated and the result inserted into the list in place. `(UNQUOTE-SPLICING expr)` is similar, but the result of evaluating `expr` must be a list, the items of which are spliced into the parent list.

#### Example

```(QUASIQUOTE (+ 1 (UNQUOTE (+ 2 3))))
```
evaluates to
```(+ 1 5)
```

If we define `L` to be the list `(3 4 5)` then

```(QUASIQUOTE (1 2 (UNQUOTE-SPLICING L)))
```
evaluates to
```(1 2 3 4 5)
```

### Shorthand syntax

Just like `QUOTE`, we will define the following abbreviations.

AbbreviationEquivalent to
``expr` `(QUASIQUOTE expr)`
`,expr` `(UNQUOTE expr)`
`,@expr` `(UNQUOTE-SPLICING expr)`

Rewriting the examples above with this syntax gives

````(+ 1 ,(+ 2 3))
```
and
````(1 2 ,@L)
```

#### Implementation

We extend the lexer to understand the additional special tokens.

```int lex(const char *str, const char **start, const char **end)
{
const char *ws = " \t\n";
const char *delim = "() \t\n";
const char *prefix = "()\'`";

str += strspn(str, ws);

if (str == '\0') {
*start = *end = NULL;
return Error_Syntax;
}

*start = str;

if (strchr(prefix, str) != NULL)
*end = str + 1;
else if (str == ',')
*end = str + (str == '@' ? 2 : 1);
else
*end = str + strcspn(str, delim);

return Error_OK;
}
```

`read_expr` must expand the abbreviations in the same way as `QUOTE`

```int read_expr(const char *input, const char **end, Atom *result)
{
.
.
.
if (token == '(') {
.
.
.
} else if (token == '`') {
*result = cons(make_sym("QUASIQUOTE"), cons(nil, nil));
} else if (token == ',') {
*result = cons(make_sym(
token == '@' ? "UNQUOTE-SPLICING" : "UNQUOTE"),
cons(nil, nil));
} else {
.
.
.
}
}
```

The `QUASIQUOTE` operator itself may be defined as a macro. First we need a few helper functions.

```(define (append a b) (foldr cons b a))

(define (caar x) (car (car x)))

(define (cadr x) (car (cdr x)))
```

`(append a b)` concatenates the lists `a` and `b`.

And now the macro itself:

```(defmacro (quasiquote x)
(if (pair? x)
(if (eq? (car x) 'unquote)
(if (eq? (caar x) 'unquote-splicing)
(list 'append
(list 'quasiquote (cdr x)))
(list 'cons
(list 'quasiquote (car x))
(list 'quasiquote (cdr x)))))
(list 'quote x)))
```

The definition above is a little hard to follow, since the resulting expression must be built up using `LIST` and may include additional calls to `QUASIQUOTE`.

Quasiquotation allows us to make the body of a macro look like the expression it returns; for example the `IGNORE` macro in chapter 11

```(DEFMACRO (IGNORE X)
(CONS 'QUOTE (CONS X NIL)))
```
can now be written
```(DEFMACRO (IGNORE X)
`(QUOTE ,X))
```
and the operation is made clear.

#### Testing

```> `(+ 1 ,(+ 2 3))
(+ 1 5)
> (define l '(3 4 5))
L
> `(1 2 ,@l)
(1 2 3 4 5)
```

## `let`

We will now use `QUASIQUOTE` to define a new special form:

```(LET ((sym1 expr1)
(sym2 expr2)
...)
body...)
```

`LET` causes the expressions `expr` to be evaluated with the symbols `sym1`, `sym2`... bound to the result of evaluating `expr1`, `expr2` and so on. The result of the last expression `body` to be evaluated is returned.

The definition is simple.

```(defmacro (let defs . body)
`((lambda ,(map car defs) ,@body)
```

#### Example

When we evaluate the form

```(LET ((X 3) (Y 5)) (+ X Y))
```
it is transformed by the `LET` macro into
```((LAMBDA (X Y) (+ X Y)) 3 5)
```
which behaves as desired.

#### Testing

```> (let ((x 3) (y 5)) (+ x y))
8
> x
Symbol not bound
```

The `LET` expression clarifies the programmer's intent to make temporary definitions.

### A trick

We can use `LET` to extend the built-in binary operator `+` to accept any number of arguments.

```(define +
(let ((old+ +))
(lambda xs (foldl old+ 0 xs))))
```

Compare this with the definition of `ADD` add the end of chapter 10.

#### Testing

```> (+ 1 2 3 4)
10
```

We didn't have to touch `builtin_add` or even recompile the interpreter.