# Macros - Fri, Nov 8

This lecture will deal with the second extra credit problem on the Scheme project.

## Programs as Data

A Scheme expression is a Scheme list. Scheme programs consist of expressions such as:

• Primitive Expressions: 2 3.3 true + quotient
• Combinations: (quotient 10 2) (not true)

The built-in Scheme list data structure (a linked list) can represent combinations

``````scm> (list `quotient 10 2)
(quotient 10 2)

scm> (eval (list `quotient 10 2))
5``````

In such a language, it is straightforward to write a program that writes a program.

Let's look at a couple of examples of a program writing a program.

### Example: Factorial

``````(define (fact n)
(if (= n 0) 1 (* n (fact (- n 1)))))

(define (fact-exp n)
(if (= n 0) 1 (list '* n (fact-exp (- n 1)))))``````

Calling `(fact 5)` yields `120`. Calling `(fact-exp 5)` yields the expression for computing `(fact 5)`: `(* 5 (* 4 (* 3 (* 2 (* 1 1)))))`

### Example: Fibonacci

``````(define (fib n)
(if (<= n 1) n (+ (fib (- n 2)) (fib (- n 1)))))

(define (fib-exp n)
(if (<= n 1) n
(list '+ (fib-exp (- n 2)) (fib-exp (- n 1)))))``````

Same idea here. `(fib-exp n)` will yield the expression for computing `(fib n)` without actually computing `(fib n)`.

## Macros

A macro is an operation performed on the source code of a program before evaluation. They exist in many languages, but are easiest to correctly define in languages like Lisp where every expression is a list.

Scheme has a `define-macro` special form that defines a source code transformation.

``````(define-macro (twice expr)
(list 'begin expr expr))

scm> (twice (print 2))			; this is equivalent to the following
scm> (begin (print 2) (print 2)); both of these print:
2
2``````

Evaluation procedure of a macro call expression:

1. Evaluate the operator sub-expression, which evaluates to a macro
2. Call the macro procedure on the operand expressions without evaluating them first
3. Evaluate the expression returned from the macro procedure

### Example: For Macro

Define a macro that evaluates an expression for each value in a sequence.

``````scm> (map (lambda (x) (* x x)) '(2 3 4 5))

(define-macro (for sym vals expr)
(list 'map (list 'lambda (list sym) expr) vals)
)

scm> (for x '(2 3 4 5) (* x x))
(4 9 16 25)``````

This example just created a `for` form in Scheme. The power of defining macros is that it allows you to extend the programming language in new ways!

## Quasi-Quotation

``````scm> '(a b c)
(a b c)

scm> `(a b c)
(a b c)

scm> (define b 3)
b

scm> `(a b c)
(a b c)

scm> `(a ,b c)
(a 3 c)``````

Quasi-quotes are the ` character, as opposed to quotes which are the ' character.

``````scm> (quasiquote (a (unquote b) c))
(a 3 c)

scm> `(a (,b) c)
(a (3) c)

scm> `(a ,(+ 2 b) c)
(a 5 c)``````

### Use Case

This allows for some simplification. Consider the following code:

``````(define-macro (check expr)
(list 'if expr ''pass
(list 'quote (list 'fail: expr))))``````

This code does the same thing as:

``````(define-macro (check expr)
`(if ,expr 'pass '(fail: ,expr)))``````