continuations. macros - the continuation passing style ...mircea.marin/lectures/fp/l-10.pdfthe...

42
Continuations. Macros The continuation passing style. Continuations in RACKET. Macro definitions May 8, 2019 Continuations. Macros

Upload: others

Post on 02-Aug-2020

3 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Continuations. Macros - The continuation passing style ...mircea.marin/lectures/FP/L-10.pdfThe continuation-passing style (CPS) Main ideas We want to make continuations manipulable

Continuations. MacrosThe continuation passing style. Continuations in RACKET.

Macro definitions

May 8, 2019

Continuations. Macros

Page 2: Continuations. Macros - The continuation passing style ...mircea.marin/lectures/FP/L-10.pdfThe continuation-passing style (CPS) Main ideas We want to make continuations manipulable

The continuation passing style

The continuation passing style (CPS) is an advanced style ofprogramming in which control is passed explicitly in the form ofa continuation:

Every function defined in CPS takes an extra argument,called continuation; whenever the function finishescomputing a value, it calls the continuation function withthe computed value.

This programming style is used often to implement compilersand interpreters for functional programming and logicprogramming.

Continuations. Macros

Page 3: Continuations. Macros - The continuation passing style ...mircea.marin/lectures/FP/L-10.pdfThe continuation-passing style (CPS) Main ideas We want to make continuations manipulable

The continuation passing style

The continuation passing style (CPS) is an advanced style ofprogramming in which control is passed explicitly in the form ofa continuation:

Every function defined in CPS takes an extra argument,called continuation; whenever the function finishescomputing a value, it calls the continuation function withthe computed value.

This programming style is used often to implement compilersand interpreters for functional programming and logicprogramming.

Continuations. Macros

Page 4: Continuations. Macros - The continuation passing style ...mircea.marin/lectures/FP/L-10.pdfThe continuation-passing style (CPS) Main ideas We want to make continuations manipulable

The intuition behind continuations

The evaluation of every expression e happens in a surroundingcontext which represents the computations that is still to be done toproduce a value. This surrounding context is called continuation.Examples of expressions in surrounding contexts:

1 (+ 5 (* 4 3))Context (or continuation) for (* 4 3): (+ 5 •).

I We must replace • with the value of (* 4 3) in thiscontext.

2 (define x 5)(if (= 0 x)

’undefined(remainder (* (+ x 1) (- x 1)) x))

Context (or continuation) for (+ x 1):

(remainder (* • (- x 1)) x))

Continuations. Macros

Page 5: Continuations. Macros - The continuation passing style ...mircea.marin/lectures/FP/L-10.pdfThe continuation-passing style (CPS) Main ideas We want to make continuations manipulable

Being more preciseContinuations as functions

We can form lambda expressions to represent continuations.Examples of continuation expressions in surrounding contexts:

Context C and expression e The continuation of e in C(+ 5 (* 4 3)) (lambda (e) (+ 4 e)(define x 5) (lambda (e)(if (= 0 x) (remainder

’undefined (* e (- x 1) x)))(remainder (* (+ x 1) (- x 1)) x))

Note:The evaluation of e in C is reduced to computing (k v)whereI k is the continuation of e in C.I v is the value of e

Continuations. Macros

Page 6: Continuations. Macros - The continuation passing style ...mircea.marin/lectures/FP/L-10.pdfThe continuation-passing style (CPS) Main ideas We want to make continuations manipulable

Being more preciseContinuations as functions

We can form lambda expressions to represent continuations.Examples of continuation expressions in surrounding contexts:

Context C and expression e The continuation of e in C(+ 5 (* 4 3)) (lambda (e) (+ 4 e)(define x 5) (lambda (e)(if (= 0 x) (remainder

’undefined (* e (- x 1) x)))(remainder (* (+ x 1) (- x 1)) x))

Note:The evaluation of e in C is reduced to computing (k v)whereI k is the continuation of e in C.I v is the value of e

Continuations. Macros

Page 7: Continuations. Macros - The continuation passing style ...mircea.marin/lectures/FP/L-10.pdfThe continuation-passing style (CPS) Main ideas We want to make continuations manipulable

The continuation-passing style (CPS)Main ideas

We want to make continuations manipulableI we extend every function with an additional argument k (its

continuation) that will be applied to the function result.I returning a value is replaced by calling the continuation.

In general, the CPS replaces every definition of a function fwith a definition of a function f-cc, such that:

(f-cc arg1 ... argn k) returns (k v)where v is the value of (f arg1 ... argn)

Continuations. Macros

Page 8: Continuations. Macros - The continuation passing style ...mircea.marin/lectures/FP/L-10.pdfThe continuation-passing style (CPS) Main ideas We want to make continuations manipulable

Illustrated examplesCPS versions of primitive operations

The CPS versions of primitive operations, like addition (+),multiplication (*), and cdr can be defined as follows:

(define (+-cc x y k) (k (+ x y)))(define (*-cc x y k) (k (* x y)))(define (cdr-cc lst k) (k (cdr lst)))

> (+-cc 1 2 list)’(3)> (*-cc 2 3 (lambda (v) (cons v v)))’(6 . 6)

Continuations. Macros

Page 9: Continuations. Macros - The continuation passing style ...mircea.marin/lectures/FP/L-10.pdfThe continuation-passing style (CPS) Main ideas We want to make continuations manipulable

Illustrated examplesSumming the elements of a list

(define (sum lst)(cond [(cons? lst) (+ (car lst) (sum (cdr lst)))]

[(null? lst) 0][#t ’undefined]))

The CPS version of sum is sum-cc defined as follows:

(define (sum-cc lst k)(cond [(cons? lst)

(sum-cc (cdr lst)(lambda (v) (k (+ (car lst) v)))); or (lambda (v) (+-cc (car lst) v k))]

[(null? lst) (k 0)][#t (k ’undefined)]))

> (sum-cc ’(1 2 3) display)6

Continuations. Macros

Page 10: Continuations. Macros - The continuation passing style ...mircea.marin/lectures/FP/L-10.pdfThe continuation-passing style (CPS) Main ideas We want to make continuations manipulable

Summing the elements of a listTracing the computation

(sum-cc ’(1 2 3) display)⇓(sum-cc ’(2 3) (lambda (e) (display (+ 1 e))))⇓(sum-cc ’(3) (lambda (e) ((lambda (e) (display (+ 1 e))) (+ 2 e))))⇓(sum-cc ’() (lambda (e)

((lambda (e)((lambda (e) (display (+ 1 e)))(+ 2 e)))

(+ 3 e))))⇓((lambda (e)

((lambda (e)((lambda (e) (display (+ 1 e)))(+ 2 e)))

(+ 3 e))))0)

⇓6

Continuations. Macros

Page 11: Continuations. Macros - The continuation passing style ...mircea.marin/lectures/FP/L-10.pdfThe continuation-passing style (CPS) Main ideas We want to make continuations manipulable

Remarks

sum-cc is tail-recursiveThe “size” of the continuation increases with eachrecursive callThe evaluation of the base-case of sum-cc istime-consuming.

Continuations. Macros

Page 12: Continuations. Macros - The continuation passing style ...mircea.marin/lectures/FP/L-10.pdfThe continuation-passing style (CPS) Main ideas We want to make continuations manipulable

Continuation-passing-style (CPS)CPS definitions of if and =

(define (if-cc test iftrue iffalse)(if test (iftrue) (iffalse)))

(define (=-cc x y k) (k (= x y)))

Remarksif-cc is the CPS version of if. It has two continuations:I iftrue for the first branchI iffalse for the second branch

Both continuations are nullary functions.

Continuations. Macros

Page 13: Continuations. Macros - The continuation passing style ...mircea.marin/lectures/FP/L-10.pdfThe continuation-passing style (CPS) Main ideas We want to make continuations manipulable

Handling exceptions in CPS

In CPS, exceptions are explicit.

Example (Definition of division in CPS)Division by 0 should raise an exception:

(define (/-cc x y k-ok k-err)(=-cc 0 y (lambda (v)

(if-cc vk-err(lambda () (k-ok (/ x y))))))))

> (/-cc 3 0 display(lambda () (display "div by zero"))

div by zero> (/-cc 3 1 display

(lambda () (display "div by zero"))3

Continuations. Macros

Page 14: Continuations. Macros - The continuation passing style ...mircea.marin/lectures/FP/L-10.pdfThe continuation-passing style (CPS) Main ideas We want to make continuations manipulable

Continuations in RACKET

RACKET has built-in support to work with continuations.It has a primitive that captures a continuation of anexpression e in a context CThe primitive is calledcall-with-current-continuation, or call/cc as ashort aliascall/cc takes a parameter, which is a function of oneparameter.The parameter of the function is bound to the continuation,and the body of the function is e

Continuations. Macros

Page 15: Continuations. Macros - The continuation passing style ...mircea.marin/lectures/FP/L-10.pdfThe continuation-passing style (CPS) Main ideas We want to make continuations manipulable

Capturing continuations with call/ccExamples

> (+ 5 (call/cc (lambda (cont) (* 4 3))))17 ; cont is bound to (lambda (e) (+ 5 e))

> (cons 1 (cons 2 (cons 3 (call/cc (lambda (k) ’()) ))))’(1 2 3) ; k is bound to (lambda (e) (cons 1 (cons 2 (cons 3 e))))

> (define x 5)> (if (= 0 x)

’undefined(remainder (* (call/cc (lambda (k) (+ x 1))) (- x 1)) x))

4 ; k is bound to (lambda (e) (remainder (* e (- x 1)) x)) where x=5

In these examples we did not do anything with the capturedcontinuations:

We can store them in a global variable, and use them later.(See next slide)

Continuations. Macros

Page 16: Continuations. Macros - The continuation passing style ...mircea.marin/lectures/FP/L-10.pdfThe continuation-passing style (CPS) Main ideas We want to make continuations manipulable

Capturing continuations with call/ccExamples

> (+ 5 (call/cc (lambda (cont) (* 4 3))))17 ; cont is bound to (lambda (e) (+ 5 e))

> (cons 1 (cons 2 (cons 3 (call/cc (lambda (k) ’()) ))))’(1 2 3) ; k is bound to (lambda (e) (cons 1 (cons 2 (cons 3 e))))

> (define x 5)> (if (= 0 x)

’undefined(remainder (* (call/cc (lambda (k) (+ x 1))) (- x 1)) x))

4 ; k is bound to (lambda (e) (remainder (* e (- x 1)) x)) where x=5

In these examples we did not do anything with the capturedcontinuations:

We can store them in a global variable, and use them later.(See next slide)

Continuations. Macros

Page 17: Continuations. Macros - The continuation passing style ...mircea.marin/lectures/FP/L-10.pdfThe continuation-passing style (CPS) Main ideas We want to make continuations manipulable

Capturing, storing, and applying continuations

> (define-values (cont-remember x) (values #t 5))> (+ 5 (call/cc (lambda (k)

(set! cont-remember k)(* 4 3))))

17 ; cont-remember is (lambda (e) (+ 5 e))> (cont-remember 3)8> (cons 1 (cons 2 (cons 3

(call/cc (lambda (k)(set! cont-remember k) ’())))))

’(1 2 3) ; cont-remember is (lambda (e) (cons 1 (cons 2 (cons 3 e))))> (cont-remember ’(7 8))’(1 2 3 7 8)> (define x 5)> (if (= 0 x)

’undefined(remainder (* (call/cc (lambda (k)

(set! cont-remember k) (+ x 1)))(- x 1))

x))4 ; cont-remember is (lambda (e) (remainder (* e (- x 1)) x))where x=5> (cont-remember 3)2

Continuations. Macros

Page 18: Continuations. Macros - The continuation passing style ...mircea.marin/lectures/FP/L-10.pdfThe continuation-passing style (CPS) Main ideas We want to make continuations manipulable

Use of continuations for escaping purposes

> (+ 5(call/cc(lambda (k)(* 4 (k 10)))) ) ; returns the value of (k 10)

15> (cons 1

(call/cc(lambda (k)(cons 2(cons3 (k ’x))))) )

’(1 . x)> (define x 5)> (if (= 0 x)

’undefined(call/cc(lambda (k)(remainder(* (+ x 1)

(- x (k 111)))x))))

111

Continuations. Macros

Page 19: Continuations. Macros - The continuation passing style ...mircea.marin/lectures/FP/L-10.pdfThe continuation-passing style (CPS) Main ideas We want to make continuations manipulable

Practical exampleComputing the length of an improper list

We wish to define (list-length lst) which returnsthe length of lst, if lst is a list’improper-list if lst is not a list.

(define (list-length l)(call/cc(lambda (do-exit)(letrec ((list-length1

(lambda (l)(cond ((null? l) 0)

((pair? l) (+ 1 (list-length1 (cdr l))))(else (do-exit ’improper-list))))))

(list-length1 l)))))

Continuations. Macros

Page 20: Continuations. Macros - The continuation passing style ...mircea.marin/lectures/FP/L-10.pdfThe continuation-passing style (CPS) Main ideas We want to make continuations manipulable

Macros

Identifiers are names of meaningful entities. In RACKET, thereare three kinds of identifiers:

1 Identifiers of special forms: cond, lambda, . . .they identify syntactic constructs with predefined rules ofevaluation.

2 Variables these are names assigned to valuesI predefined: pi, sin, +, . . .I defined by the user

3 Macro-identifier

Continuations. Macros

Page 21: Continuations. Macros - The continuation passing style ...mircea.marin/lectures/FP/L-10.pdfThe continuation-passing style (CPS) Main ideas We want to make continuations manipulable

What are macros?

A macro is an expression (macro-id . . .)where macro-id is a macro-identifier.

A macro is like a function call, but:I a function call is computed by the interpreterI a macro is a call of a syntax transformer

macro-id is the name of a syntax transformer.I the syntax transformer is special function which indicates

how to transform a syntactic construct e into anothersyntactic construct e′.

e′ is called the expansion of e

I The expansion of e is computed in the expansion phase, bythe preprocessor (or expander) of RACKET

I Afterwards, the interpreter computes the value of theexpansion of e.

Continuations. Macros

Page 22: Continuations. Macros - The continuation passing style ...mircea.marin/lectures/FP/L-10.pdfThe continuation-passing style (CPS) Main ideas We want to make continuations manipulable

The evaluation of macros

(macro-id . . .)

expansion e′

value of e′

expansion (performed by the expander)

evaluation (performed by the interpreter)

macro-id is either predefined or user-defined.

How to define macros?1 with define-syntax-rule (the easy way).2 with a combination of define-syntax andsyntax-rules (the more complicated way)

Continuations. Macros

Page 23: Continuations. Macros - The continuation passing style ...mircea.marin/lectures/FP/L-10.pdfThe continuation-passing style (CPS) Main ideas We want to make continuations manipulable

The evaluation of macros

(macro-id . . .)

expansion e′

value of e′

expansion (performed by the expander)

evaluation (performed by the interpreter)

macro-id is either predefined or user-defined.

How to define macros?1 with define-syntax-rule (the easy way).2 with a combination of define-syntax andsyntax-rules (the more complicated way)

Continuations. Macros

Page 24: Continuations. Macros - The continuation passing style ...mircea.marin/lectures/FP/L-10.pdfThe continuation-passing style (CPS) Main ideas We want to make continuations manipulable

Macro definitionsDefinitions with define-syntax-rule

Example (Swap the values of two variables)We want to write (swap x y) instead of

(let ([tmp x])(set! x y)(set! y tmp)

We can use define-syntax-rule to define the macro swap:

(define-syntax-rule (swap x y)(let ([tmp x])(set! x y)(set! y tmp)))

The blue part is called the template of the syntax rule.

Continuations. Macros

Page 25: Continuations. Macros - The continuation passing style ...mircea.marin/lectures/FP/L-10.pdfThe continuation-passing style (CPS) Main ideas We want to make continuations manipulable

Macro definitionsDefinitions with define-syntax-rule

Example (Swap the values of two variables)We want to write (swap x y) instead of

(let ([tmp x])(set! x y)(set! y tmp)

We can use define-syntax-rule to define the macro swap:

(define-syntax-rule (swap x y)(let ([tmp x])

(set! x y)(set! y tmp)))

The blue part is called the template of the syntax rule.

Continuations. Macros

Page 26: Continuations. Macros - The continuation passing style ...mircea.marin/lectures/FP/L-10.pdfThe continuation-passing style (CPS) Main ideas We want to make continuations manipulable

Evaluation of macro definitionsExamples

> (define a 1)> (define b 2)> (list a b)’(1 2)> (swap a b) ; same as (let ([tmp a]) (set! a b) (set! b tmp))’(2 1)> (swap a 1) ; same as (let ([tmp a]) (set! a 1) (set! 1 tmp))set!: not an identifier in: 1

Remarks1 A syntax transformer transforms syntactic structures. To

avoid errors, we must make sure we call it with argumentsof the right kind!

Continuations. Macros

Page 27: Continuations. Macros - The continuation passing style ...mircea.marin/lectures/FP/L-10.pdfThe continuation-passing style (CPS) Main ideas We want to make continuations manipulable

Evaluation of macro definitionsExamples

> (define a 1)> (define b 2)> (list a b)’(1 2)> (swap a b) ; same as (let ([tmp a]) (set! a b) (set! b tmp))’(2 1)> (swap a 1) ; same as (let ([tmp a]) (set! a 1) (set! 1 tmp))set!: not an identifier in: 1

Remarks1 A syntax transformer transforms syntactic structures. To

avoid errors, we must make sure we call it with argumentsof the right kind!

Continuations. Macros

Page 28: Continuations. Macros - The continuation passing style ...mircea.marin/lectures/FP/L-10.pdfThe continuation-passing style (CPS) Main ideas We want to make continuations manipulable

Things you should never do

In RACKET, we can define the identifiers of special forms asvariables (you should never do this!)

> (define set! 4)> set! ; set! is now a variable with value 4> (set! a 6) ; we can not use the special form set! anymore because we redefined itapplication: not a procedure; ...

Continuations. Macros

Page 29: Continuations. Macros - The continuation passing style ...mircea.marin/lectures/FP/L-10.pdfThe continuation-passing style (CPS) Main ideas We want to make continuations manipulable

Syntax transformers are clever

> (define tmp 5) (define a 6)> (swap tmp a) ; swap the values of tmp and a> (list tmp a)’(6 5)

It works but ... WHY?

A naive syntax transformer replaces (swap tmp a) with

> (let ([tmp tmp])(set! tmp a)(set! a tmp)))

⇒ we don’t distinguish between variable tmp at expansion time, and tmp atevaluation time: Their names clash! This is not what we want.

The expander is clever! It renames tmp at expansion time to avoid nameclashes:

The expansion of (swap tmp a) is(let ([tmp1 tmp] (set! tmp a) (set! a tmp1)))

Continuations. Macros

Page 30: Continuations. Macros - The continuation passing style ...mircea.marin/lectures/FP/L-10.pdfThe continuation-passing style (CPS) Main ideas We want to make continuations manipulable

Syntax transformers are clever

> (define tmp 5) (define a 6)> (swap tmp a) ; swap the values of tmp and a> (list tmp a)’(6 5)

It works but ... WHY?

A naive syntax transformer replaces (swap tmp a) with

> (let ([tmp tmp])(set! tmp a)(set! a tmp)))

⇒ we don’t distinguish between variable tmp at expansion time, and tmp atevaluation time: Their names clash! This is not what we want.

The expander is clever! It renames tmp at expansion time to avoid nameclashes:

The expansion of (swap tmp a) is(let ([tmp1 tmp] (set! tmp a) (set! a tmp1)))

Continuations. Macros

Page 31: Continuations. Macros - The continuation passing style ...mircea.marin/lectures/FP/L-10.pdfThe continuation-passing style (CPS) Main ideas We want to make continuations manipulable

Syntax transformers are clever

> (define tmp 5) (define a 6)> (swap tmp a) ; swap the values of tmp and a> (list tmp a)’(6 5)

It works but ... WHY?

A naive syntax transformer replaces (swap tmp a) with

> (let ([tmp tmp])(set! tmp a)(set! a tmp)))

⇒ we don’t distinguish between variable tmp at expansion time, and tmp atevaluation time: Their names clash! This is not what we want.

The expander is clever! It renames tmp at expansion time to avoid nameclashes:

The expansion of (swap tmp a) is(let ([tmp1 tmp] (set! tmp a) (set! a tmp1)))

Continuations. Macros

Page 32: Continuations. Macros - The continuation passing style ...mircea.marin/lectures/FP/L-10.pdfThe continuation-passing style (CPS) Main ideas We want to make continuations manipulable

The interpreter is cleverWhat happens if, at evaluation time we use variables whose names clash with theidentifiers of special forms used in the template of the syntax rule?

> (let ([set! 5][a 6])

(swap set! a) ; set! gets value 6 and a gets value 5(list set! a)) ; should return ’(6 5)

> ’(6 5)

it works but ... WHY?

A naive syntax transformer produces(let ([set! 5]

[a 6])(let ([tmp set!])(set! set! a) ←name clash!(set! a tmp)))

(list set! a))

The interpreter avoids name clashes too:(let ([set!1 5] set! was renamed to set!1

[a 6])(let ([tmp set!1])(set! set!1 a)(set! a tmp)))

(list set!1 a))

Continuations. Macros

Page 33: Continuations. Macros - The continuation passing style ...mircea.marin/lectures/FP/L-10.pdfThe continuation-passing style (CPS) Main ideas We want to make continuations manipulable

The interpreter is cleverWhat happens if, at evaluation time we use variables whose names clash with theidentifiers of special forms used in the template of the syntax rule?

> (let ([set! 5][a 6])

(swap set! a) ; set! gets value 6 and a gets value 5(list set! a)) ; should return ’(6 5)

> ’(6 5)

it works but ... WHY?A naive syntax transformer produces(let ([set! 5]

[a 6])(let ([tmp set!])

(set! set! a) ←name clash!(set! a tmp)))

(list set! a))

The interpreter avoids name clashes too:(let ([set!1 5] set! was renamed to set!1

[a 6])(let ([tmp set!1])

(set! set!1 a)(set! a tmp)))

(list set!1 a))

Continuations. Macros

Page 34: Continuations. Macros - The continuation passing style ...mircea.marin/lectures/FP/L-10.pdfThe continuation-passing style (CPS) Main ideas We want to make continuations manipulable

The evaluation of macros

RemarkRACKET always renames the variables to avoid the interferenceof variables with the same name at expansion time and atevaluation time.

Continuations. Macros

Page 35: Continuations. Macros - The continuation passing style ...mircea.marin/lectures/FP/L-10.pdfThe continuation-passing style (CPS) Main ideas We want to make continuations manipulable

Macro definitionsDefinitions with define-syntax and syntax-rules

This method is used to define syntax transformers with syntax rulesfor multiple patterns

(define-syntax macro-id(syntax-rules (literal-id1 ... literal-idm)[pat1 template1]...[patn templaten]))

where every pati must be of the form (macro-id . . .).

Example

(define-syntax prefs(syntax-rules ()[(prefs) null][(prefs a) ’(() (a))][(prefs a b) ’(() (a) (a b))]))

> (prefs (+ 1 2) (+ 3 4)) ; apply third syntax rule’(() ((+ 1 2)) ((+ 1 2) (+ 3 4)))> (prefs 1 2 3) ; no syntax rule us applicableprefs: bad syntax in: ...

Continuations. Macros

Page 36: Continuations. Macros - The continuation passing style ...mircea.marin/lectures/FP/L-10.pdfThe continuation-passing style (CPS) Main ideas We want to make continuations manipulable

Macro definitionsDefinitions with define-syntax and syntax-rules

This method is used to define syntax transformers with syntax rulesfor multiple patterns

(define-syntax macro-id(syntax-rules (literal-id1 ... literal-idm)[pat1 template1]...[patn templaten]))

where every pati must be of the form (macro-id . . .).

Example

(define-syntax prefs(syntax-rules ()[(prefs) null][(prefs a) ’(() (a))][(prefs a b) ’(() (a) (a b))]))

> (prefs (+ 1 2) (+ 3 4)) ; apply third syntax rule’(() ((+ 1 2)) ((+ 1 2) (+ 3 4)))> (prefs 1 2 3) ; no syntax rule us applicableprefs: bad syntax in: ...

Continuations. Macros

Page 37: Continuations. Macros - The continuation passing style ...mircea.marin/lectures/FP/L-10.pdfThe continuation-passing style (CPS) Main ideas We want to make continuations manipulable

Macro patterns with matching sequences

Let’s define the macro (split-last a1 . . . an) which expands to’((a1 . . . an−1) an) if n > 0, and to ’(() ()) if n = 0.

> (define-syntax split-last(syntax-rules ()

[(split-last) ’(() ())][(split-last as ... b) ’((as ...) b)]))

> (split-last)’(() ())> (split-last a)’(() (a))> (split-last 1 (+ 2 3) 3 (/ 6 2))’((1 (+ 2 3) 3) (/ 6 2))

Pattern variables followed by ... match sequences of syntactic expressions.In the previous example:

as matches all arguments of split-last except the last one

b matches the lat argument.

Continuations. Macros

Page 38: Continuations. Macros - The continuation passing style ...mircea.marin/lectures/FP/L-10.pdfThe continuation-passing style (CPS) Main ideas We want to make continuations manipulable

Macro patterns with matching sequences

Let’s define the macro (split-last a1 . . . an) which expands to’((a1 . . . an−1) an) if n > 0, and to ’(() ()) if n = 0.

> (define-syntax split-last(syntax-rules ()

[(split-last) ’(() ())][(split-last as ... b) ’((as ...) b)]))

> (split-last)’(() ())> (split-last a)’(() (a))> (split-last 1 (+ 2 3) 3 (/ 6 2))’((1 (+ 2 3) 3) (/ 6 2))

Pattern variables followed by ... match sequences of syntactic expressions.In the previous example:

as matches all arguments of split-last except the last one

b matches the lat argument.

Continuations. Macros

Page 39: Continuations. Macros - The continuation passing style ...mircea.marin/lectures/FP/L-10.pdfThe continuation-passing style (CPS) Main ideas We want to make continuations manipulable

A more intricate exampleA user-defined macro for and

(and e1 e2 . . . en) is logically equivalent with

(if e1 (if e2 e2 (... (if en−1 en en−1) ...)) e1)

Let’s define (my-and e1 e2 . . . en) to expand into e1 if n = 1,and the equivalent nested if expression otherwise:

(define-syntax my-and(syntax-rules ()

[(my-and a) a][(my-and a b ...) (if a (my-and b ...) a)]))

RemarksThe expansion of (my-and e1 e2 . . . en) may requireseveral expansion steps, because my-and is definedrecursively.Only when all expansions end, will the interpreter start toevaluate the fully expanded expression.

Continuations. Macros

Page 40: Continuations. Macros - The continuation passing style ...mircea.marin/lectures/FP/L-10.pdfThe continuation-passing style (CPS) Main ideas We want to make continuations manipulable

A more intricate exampleA user-defined macro for and

(and e1 e2 . . . en) is logically equivalent with

(if e1 (if e2 e2 (... (if en−1 en en−1) ...)) e1)

Let’s define (my-and e1 e2 . . . en) to expand into e1 if n = 1,and the equivalent nested if expression otherwise:

(define-syntax my-and(syntax-rules ()

[(my-and a) a][(my-and a b ...) (if a (my-and b ...) a)]))

RemarksThe expansion of (my-and e1 e2 . . . en) may requireseveral expansion steps, because my-and is definedrecursively.Only when all expansions end, will the interpreter start toevaluate the fully expanded expression.

Continuations. Macros

Page 41: Continuations. Macros - The continuation passing style ...mircea.marin/lectures/FP/L-10.pdfThe continuation-passing style (CPS) Main ideas We want to make continuations manipulable

A more intricate exampleA user-defined macro for and

(and e1 e2 . . . en) is logically equivalent with

(if e1 (if e2 e2 (... (if en−1 en en−1) ...)) e1)

Let’s define (my-and e1 e2 . . . en) to expand into e1 if n = 1,and the equivalent nested if expression otherwise:

(define-syntax my-and(syntax-rules ()

[(my-and a) a][(my-and a b ...) (if a (my-and b ...) a)]))

RemarksThe expansion of (my-and e1 e2 . . . en) may requireseveral expansion steps, because my-and is definedrecursively.Only when all expansions end, will the interpreter start toevaluate the fully expanded expression.

Continuations. Macros

Page 42: Continuations. Macros - The continuation passing style ...mircea.marin/lectures/FP/L-10.pdfThe continuation-passing style (CPS) Main ideas We want to make continuations manipulable

Macro patterns with matching sequencesA useful use of ... in rule templates

If to and from are macro pattern variables that match sequences of same length,and to is bound to a sequence of identifiers, then

(set! to from) ...

in the template causes the duplication of set! as many times as necessary, to use eachidentifier matched in the to and from sequences.

Example

> (define-syntax-rule (my-set! (xs ...) (vs ...))(local [] (set! xs vs) ... (list xs ...)))

> (define-values (x y z) (values 9 8 7))> (list x y z)’(9 8 7)> ; this macro expands to

; (local [] (set! x 1) (set! y 2) (set! z 3) (list x y z))(my-set! (x y z) (1 2 3))

> (list x y z)’(1 2 3)

Continuations. Macros