The Reasoned Schemer
The Reasoned Schemer
The Reasoned Schemer
Daniel P. Friedman
William E. Byrd
Oleg Kiselyov
Drawings by Duane Bibby
All rights reserved. No part of this book may be reproduced in any form by any electronic
or mechanical means (including photocopying, recording, or information storage and retrieval)
without permission in writing from the publisher.
MIT Press books may be purchased at special quantity discounts for business or sales promotional use. For information, please e-mail special sales@mitpress.mit.edu or write to
Special Sales Department, The MIT Press, 55 Hayward Street, Cambridge, Mass. 02142.
This book was set in Computer Modern by the authors using LATEX. Printed and bound in the
United States of America.
Library of Congress Cataloging-in-Publication Data
Friedman, Daniel P.
The reasoned schemer / Daniel P. Friedman, William E. Byrd, and Oleg Kiselyov; drawings
by Duane Bibby.
p. cm.
Includes index.
ISBN 0-262-56214-6 (pbk. : alk. paper)
1. Scheme (Computer program language) I. Byrd, William E. II. Kiselyov, Oleg. III. Title.
QA76.73.S34F76
005.13! 3dc22
2005
10 9 8 7 6 5 4 3 2 1
2005051092
((Contents)
(Preface ix)
((1. Playthings) 2)
((2. Teaching Old Toys New Tricks) 16)
((3. Seeing Old Friends in New Ways) 26)
((4. Members Only) 46)
((5. Double Your Fun) 60)
((6. The Fun Never Ends . . . ) 76)
((7. A Bit Too Much) 86)
((8. Just a Bit More) 108)
((9. Under the Hood) 130)
((10. Thin Ice) 144)
(Connecting the Wires 158)
(Welcome to the Club 162)
(Index 164))
Preface
The goal of this book is to show the beauty of relational programming. We believe that it is
natural to extend functional programming to relational programming. We demonstrate this by
extending Scheme with a few new constructs, thereby combining the benefits of both styles. This
extension also captures the essence of Prolog, the most well-known logic programming language.
Our main assumption is that you understand the first eight chapters of The Little Schemer 1 .
The only true requirement, however, is that you understand functions as values. That is, a
function can be both an argument to and the value of a function call. Furthermore, you should
know that functions remember the context in which they were created. And thats itwe
assume no further knowledge of mathematics or logic. Readers of the appendix Connecting
the Wires, however, must also have a rudimentary knowledge of Scheme macros at the level of
let, and, and cond.
In order to do relational programming, we need only two constants: #s and #u, and only
three operators: , fresh, and conde . These are introduced in the first chapter and are the
only operators used until chapter 6. The additional operators we introduce are variants of these
three. In order to keep this extension simple, we mimicked existing Scheme syntax. Thus, #s
and #u are reminiscent of the Boolean constants: #t and #f; fresh expressions resemble lambda
expressions; and conde expressions are syntactically like cond expressions.
We use a few notational conventions throughout the textprimarily changes in font for
different classes of symbols. Lexical variables are in italics, forms are in boldface, data are
in sans serif, and lists are wrapped by boldfaced parentheses ((). A relation, a function that
returns a goal as its value, ends its name with a superscript o (e.g., car o and null o ). We also
use a superscript with our interface to Scheme, run, which is fully explained in the first chapter.
We have taken certain liberties with punctuation to increase clarity, such as frequently omitting
a question mark when a question ends with a special symbol. We do this to avoid confusion
with function names that might end with a question mark.
In chapters 7 and 8 we define arithmetic operators as relations. The +o relation can not
only add but also subtract; o can not only multiply but also factor numbers; and log o can not
only find the logarithm given a number and a base but also find the base given a logarithm and
a number. Just as we can define the subtraction relation from the addition relation, we can
define the exponentiation relation from the logarithm relation.
In general, given (o x y z ) we can specify what we know about these numbers (their values,
whether they are odd or even, etc.) and ask o to find the unspecified values. We dont specify
how to accomplish the task; rather, we describe what we want in the result.
1 Friedman,
Preface
Daniel P., and Matthias Felleisen. The Little Schemer, fourth ed. MIT Press, 1996.
ix
This book would not have been possible without earlier work on implementing and using
logic systems with Matthias Felleisen, Anurag Mendhekar, Jon Rossie, Michael Levin, Steve
Ganz, and Venkatesh Choppella. Steve showed how to partition Prologs named relations into
unnamed functions, while Venkatesh helped characterize the types in this early logic system.
We thank them for their effort during this developmental stage.
There are many others we wish to thank. Mitch Wand struggled through an early draft and
spent several days in Bloomington clarifying the semantics of the language, which led to the
elimination of superfluous language forms. We also appreciate Kent Dybvigs and Yevgeniy
Makarovs comments on the first few chapters of an early draft and Amr Sabrys Haskell
implementation of the language.
We gratefully acknowledge Abdulaziz Ghuloums insistence that we remove some abstract
material from the introductory chapter. In addition, Azizs suggestions significantly clarified the
run interface. Also incredibly helpful were the detailed criticisms of Chung-chieh Shan, Erik
Hilsdale, John Small, Ronald Garcia, Phill Wolf, and Jos Koot. We are especially grateful to
Chung-chieh for Connecting the Wires so masterfully in the final implementation.
We thank David Mack and Kyle Blocher for teaching this material to students in our
undergraduate programming languages course and for making observations that led to many
improvements to this book. We also thank those students who not only learned from the
material but helped us to clarify its presentation.
There are several people we wish to thank for contributions not directly related to the
ideas in the book. We would be remiss if we did not acknowledge Dorai Sitarams incredibly
clever Scheme typesetting program, SLATEX. We are grateful for Matthias Felleisens typesetting
macros (created for The Little Schemer ), and for Oscar Waddells implementation of a tool that
selectively expands Scheme macros. Also, we thank Shriram Krishnamurthi for reminding us of
a promise we made that the food would be vegetarian in the next little book. Finally, we thank
Bob Prior, our editor, for his encouragement and enthusiasm for this effort.
Food appears in examples throughout the book for two reasons. First, food is easier to
visualize than abstract symbols; we hope the food imagery helps you to better understand the
examples and concepts. Second, we want to provide a little distraction. We know how frustrating
the subject matter can be, thus these culinary diversions are for whetting your appetite. As
such, we hope that thinking about food will cause you to stop reading and have a bite.
You are now ready to start. Good luck! We hope you enjoy the book.
Bon appetit!
Daniel P. Friedman
William E. Byrd
Bloomington, Indiana
Oleg Kiselyov
Monterey, California
Preface
Chapter 1
Playthings
Welcome.
It is good to be here.
#f.
Well. . .
#t.
Absolutely.
What is #s
succeed,
because it succeeds.
#s is written succeed.
What is #u
#u is written fail.
Playthings
10
(run (q)
#u)
fail,
because it fails.
(),
since #u fails, and because the expression
(run (q) g . . . )
has the value () if any goal in g . . . fails.
11
(run (q)
( #t q))
(#t)),
because #t is associated with q if ( #t q)
succeeds.
12
(run (q)
#u
( #t q))
(),
because the expression
(run (q) g . . . ( #t q))
has the value () if the goals g . . . fail.
13
#t (a Boolean value),
because the expression
(run (q) g . . . ( #t q))
associates #t with q if the goals g . . . and
( #t q) succeed.
Chapter 1
14
(run (q)
#s
( #t q))
15
(run (r )
#s
( corn r ))
(#t)),
because #s succeeds.
corn ,
because r is associated with corn when
( corn r ) succeeds.
16
(run (r )
#s
( corn r ))
17
(run (r )
#u
( corn r ))
18
(run (q)
#s
( #f q))
Does
19
(corn)),
because r is associated with corn when
( corn r ) succeeds.
(),
because #u fails.
(#f)),
because #s succeeds and because run
returns a nonempty list if its goals succeed.
( #f x )
succeed?
Playthings
Does
20
No,
since #f is not equal to #t.
21
Yes,
since #f is equal to #f.
Does
(let ((x #f))
( #f x ))
succeed?
22
(run (x )
(let ((x #f))
( #t x )))
23
(run (q)
(fresh (x )
( #t x )
( #t q)))
(),
since #t is not equal to #f.
#t,
because (fresh (x . . . ) g . . . ) binds fresh
variables to x . . . and succeeds if the goals
g . . . succeed. ( v x ) succeeds when x is
fresh.
24
25
No,
since q also starts out fresh.
(run (q)
(fresh (x )
( #t x )
( #t q)))
Chapter 1
26
(run (q)
(fresh (x )
( x #t)
( #t q)))
27
(run (q)
(fresh (x )
( x #t)
( q #t)))
#t,
because the order of arguments to does
not matter.
#t,
because the order of arguments to does
not matter.
The Law of
( v w ) is the same as ( w v ).
28
(run (x )
#s)
,
a symbol representing a fresh variable.
Playthings
29
(run (x )
(let ((x #f))
(fresh (x )
( #t x ))))
30
( 0 ),
since the x in ( #t x ) is the one
introduced by the fresh expression; it is
neither the x introduced in the run
expression nor the x introduced in the
lambda expression.
(
(run (r )
(fresh (x y)
( (cons x (cons y () )) r )))
() is (quote ()).
31
(run (r )
(fresh (x )
(let ((y x ))
(fresh (x )
( (cons y (cons x (cons y ()))) r )))))
33
1 ).
The expressions in this and the previous
frame differ only in the names of the
lexical variables. Therefore the values are
the same.
(run (s)
(fresh (t u)
( (cons t (cons u ())) s)))
32
).
1
For each different fresh variable there is a
symbol with an underscore followed by a
numeric subscript. This entity is not a
variable but rather is a way of showing
that the variable was fresh. We say that
such a variable has been reified .
1
0 ).
Within the inner fresh, x and y are
different variables, and since they are still
fresh, they get different reified names.
).
1
0
x
and
y are different variables, and since
(run (r )
they
are
still fresh, they get different
(fresh (x )
reified
names.
Reifying r s value reifies the
(let ((y x ))
fresh
variables
in the order in which they
(fresh (x )
( (cons x (cons y (cons x ()))) r ))))) appear in the list.
(
Chapter 1
34
(run (q)
( #f q)
( #t q))
35
(run (q)
( #f q)
( #f q))
36
(run (q)
(let ((x q))
( #t x )))
37
(run (r )
(fresh (x )
( x r ) ))
38
(run (q)
(fresh (x )
( #t x )
( x q)))
Playthings
39
().
The first goal ( #f q) succeeds,
associating #f with q; #t cannot then be
associated with q, since q is no longer
fresh.
(#f)).
In order for the run to succeed, both
( #f q) and ( #f q) must succeed. The
first goal succeeds while associating #f
with the fresh variable q. The second goal
succeeds because although q is no longer
fresh, #f is already associated with it.
#t,
because q and x are the same.
,
because r starts out fresh and then r gets
whatever association that x gets, but both
x and r remain fresh. When one variable
is associated with another, we say they
co-refer or share.
#t,
because q starts out fresh and then q gets
x s association.
#t,
because the first goal ensures that
whatever association x gets, q also gets.
40
(run (q)
(fresh (x )
( #t x )
( x q)))
and
(run (q)
(let ((x q))
(fresh (q)
( (eq? x q) x ))))
associate #f with q. Every variable
introduced by fresh (or run) is different
from every other variable introduced by
fresh (or run).
41
(cond
(#f #t)
(else #f))
42
Does
43
(cond
(#f #s)
(else #u))
#f,
because the question of the first cond line
is #f, so the value of the cond expression is
determined by the answer in the second
cond line.
No,
it fails because the answer of the second
cond line is #u.
succeed?
10
Chapter 1
Does
44
No,
because the question of the first conde line
is the goal #u.
45
Yes,
because the question of the first conde line
is the goal #u, so conde tries the second
line.
46
Yes,
because the question of the first conde line
is the goal #s, so conde tries the answer of
the first line.
(cond
(#u #s)
(else #u))
e
succeed?
Does
(cond
(#u #u)
(else #s))
e
succeed?
Does
(conde
(#s #s)
(else #u))
succeed?
Playthings
47
(olive oil)),
because ( olive x ) succeeds; therefore, the
answer is #s. The #s preserves the
association of x to olive. To get the second
value, we pretend that ( olive x ) fails;
this imagined failure refreshes x . Then
( oil x ) succeeds. The #s preserves the
association of x to oil. We then pretend
that ( oil x ) fails, which once again
refreshes x . Since no more goals succeed,
we are done.
11
48
49
(run1 (x )
(conde
(( olive x ) #s)
(( oil x ) #s)
(else #u)))
(olive)),
because ( olive x ) succeeds and because
run1 produces at most one value.
50
(run (x )
(conde
(( virgin x ) #u)
(( olive x ) #s)
(#s #s)
(( oil x ) #s)
(else #u)))
12
(olive 0 oil)).
Once the first conde line fails, it is as if
that line were not there. Thus what results
is identical to
(conde
(( olive x ) #s)
(#s #s)
(( oil x ) #s)
(else #u)).
51
(#s #s),
since it succeeds without x getting an
association.
Chapter 1
52
(run (x )
(conde
(( extra x ) #s)
(( virgin x ) #u)
(( olive x ) #s)
(( oil x ) #s)
(else #u)))
2
(extra olive)),
since we do not want every value; we want
only the first two values.
53
(split pea)).
(run (r )
(fresh (x y)
( split x )
( pea y)
( (cons x (cons y ())) r )))
54
(run (r )
(fresh (x y)
(conde
(( split x ) ( pea y))
(( navy x ) ( bean y))
(else #u))
( (cons x (cons y ())) r )))
55
(run (r )
(fresh (x y)
(conde
(( split x ) ( pea y))
(( navy x ) ( bean y))
(else #u))
( (cons x (cons y (cons soup ()))) r )))
Playthings
13
56
(tea cup)).
(define teacup o
(lambda (x )
(conde
(( tea x ) #s)
(( cup x ) #s)
(else #u))))
What is the value of
(run (x )
(teacup o x ))
57
(run (r )
(fresh (x y)
(conde
((teacup o x ) ( #t y) #s)
(( #f x ) ( #t y))
(else #u))
( (cons x (cons y ())) r )))
14
58
((
0
1) ( 0
1 )),
but it looks like both occurrences of 0
have come from the same variable and
similarly for both occurrences of 1 .
Chapter 1
59
60
(run (q)
(let ((a ( #t q))
(b ( #f q)))
b))
61
((#f 0 ) ( 0 #f))),
which clearly shows that the two
occurrences of 0 in the previous frame
represent different variables.
JAM STAINS!
Playthings
15
Chapter 2
c,
(run (r )
(fresh (y x )
( (x y)) r )))
((
(run (r )
(fresh (v w )
( (let ((x v ) (y w )) (x y))) r )))
) ,
because the variables in (x y)) have been
introduced by fresh.
)),
0
1
because v and w are variables introduced
by fresh.
grape.
a.
a,
17
(run (q)
(car o (a c o r n)) a)
( #t q))
pear,
since x is associated with the car of (r y)),
which is the fresh variable r . Then x is
associated with pear, which in turn
associates r with pear.
(run (r )
(fresh (x y)
(car o (r y)) x )
( pear x )))
#t,
because a is the car of (a c o r n)).
(define car o
(lambda (p a)
(fresh (d )
( (cons a d ) p))))
What is unusual about this definition?
10
(cons
(car (grape raisin pear)))
(car ((a)) (b)) (c)))))
11
(run (r )
(fresh (x y)
(car o (grape raisin pear)) x )
(car o ((a)) (b)) (c))) y)
( (cons x y) r )))
18
12
Chapter 2
13
14
c.
15
c.
16
(define cdr o
(lambda (p d )
(fresh (a)
( (cons a d ) p))))
17
(cons
(cdr (grape raisin pear)))
(car ((a)) (b)) (c)))))
18
(run (r )
(fresh (x y)
(cdr o (grape raisin pear)) x )
(car o ((a)) (b)) (c))) y)
( (cons x y) r )))
19
19
(run (q)
(cdr o (a c o r n)) (c o r n)))
( #t q))
20
#t,
because (c o r n)) is the cdr of (a c o r n)).
o,
(run (x )
(cdr o (c o r n)) (x r n))))
21
(run (l )
(fresh (x )
(cdr o l (c o r n)))
(car o l x )
( a x )))
22
(run (l )
(cons o (a b c)) (d e)) l ))
23
(a c o r n)),
because if the cdr of l is (c o r n)), then l
must be the list (a c o r n)), where a is the
fresh variable introduced in the definition
of cdr o . Taking the car o of l associates the
car of l with x . When we associate x with
a, we also associate a, the car of l , with a,
so l is associated with the list (a c o r n)).
((a b c)) d e)),
since cons o associates l with
(cons (a b c)) (d e))).
d.
(run (x )
(cons o x (a b c)) (d a b c))))
24
(run (r )
(fresh (x y z )
( (e a d x ) r )
(cons o y (a z c)) r )))
20
25
(e a d c)),
because first we associate r with a list
whose last element is the fresh variable x .
We then perform the cons o , associating x
with c, z with d, and y with e.
d.
Chapter 2
26
(run (l )
(fresh (x )
( (d a x c)) l )
(cons o x (a x c)) l )))
27
(run (l )
(fresh (x )
(cons o x (a x c)) l )
( (d a x c)) l )))
28
29
(d a d c)),
because we cons x onto (a x c)), and
associate l with the list (x a x c)). Then
when we associate l with (d a x c)), we
associate x with d.
(define cons o
(lambda (a d p)
( (cons a d ) p)))
(run (l )
(fresh (d x y w s)
(cons o w (a n s)) s)
(cdr o l s)
(car o l x )
( b x )
(cdr o l d )
(car o d y)
( e y)))
(d a d c)),
because l is (d a x c)). Then when we
cons o x onto (a x c)), we associate x with
d.
30
(b e a n s)).
l must clearly be a five element list, since s
is (cdr l ). Since l is fresh, (cdr o l s) places
a fresh variable in the first position of l ,
while associating w and (a n s)) with the
second position and the cdr of the cdr of l ,
respectively. The first variable in l gets
associated with x , which in turn gets
associated with b. The cdr of l is a list
whose car is the variable w . That variable
gets associated with y, which in turn gets
associated with e.
#f.
31
#t.
(null? ())
21
32
().
(run (q)
(null o (grape raisin pear)))
( #t q))
33
(#t)).
(run (q)
(null o ())
( #t q))
34
(()).
(run (x )
(null o x ))
35
36
(define null o
(lambda (x )
( () x )))
#f.
37
#t.
38
().
(run (q)
(eq o pear plum)
( #t q))
22
Chapter 2
39
(#t)).
(run (q)
(eq o plum plum)
( #t q))
Define eq o using .
40
It is easy.
(define eq o
(lambda (x y)
( x y)))
41
Yes.
Is (split ! x ) a pair?
42
Yes.
43
#t.
44
#f.
(pair? ())
Is pair a pair?
45
No.
Is pear a pair?
46
No.
47
Yes,
it is the pair (pear ! ()).
48
pear.
Is (pear)) a pair?
23
49
().
(cdr (pear)))
50
51
((split)) ! pea)).
52
! salad)).
(run (r )
(fresh (x y)
( (cons x (cons y salad)) r )))
53
No, it is not.
(define pair o
(lambda (p)
(fresh (a d )
(cons o a d p))))
Is pair o recursive?
54
(#t)).
(run (q)
(pair o (cons q q))
( #t q))
55
().
(run (q)
(pair o ())
( #t q))
24
Chapter 2
56
().
(run (q)
(pair o pair)
( #t q))
57
).
(run (x )
(pair o x ))
58
(run (r )
(pair o (cons r pear)))
59
Yes.
25
Chapter 3
#t.
(define list?
(lambda (l )
(cond
((null? l ) #t)
((pair? l ) (list? (cdr l )))
(else #f))))
What is the value of
(list? ((a)) (a b)) c)))
#t.
(list? ())
#f.
(list? s)
(list? (d a t e ! s)))
#f,
because (d a t e ! s)) is not a proper list.
27
Where does
(fresh (d )
(cdr o l d )
(list o d ))
come from?
(run (x )
(list o (a b x d)) ))
,
since x remains fresh.
Why is
(run (x )
(list o (a b x d))))
How is
(run (x )
(list o (a b x d))))
28
Chapter 3
10
().
(run (x )
(list o (a b c ! x )))
1
11
12
13
It has no value.
Maybe we should use run5 to get the first
five values.
(run (x )
(list o (a b c ! x )))
1
14
(run (x )
(list o (a b c ! x )))
5
15
(()
( 0)
( 0 1)
( 0 1 2)
( 0 1 2 3 )).
29
16
17
(define lol?
(lambda (l )
(cond
((null? l ) #t)
((list? (car l )) (lol? (cdr l )))
(else #f))))
Describe what lol? does.
30
18
19
20
Yes.
(()).
Since l is fresh, (null o l ) succeeds and in
the process associates l with ().
Chapter 3
21
(run (q)
(fresh (x y)
(lol o ((a b)) (x c)) (d y))))
( #t q)))
22
(run (q)
(fresh (x )
(lol o ((a b)) ! x ))
( #t q)))
1
23
(run (x )
(lol o ((a b)) (c d)) ! x )))
1
24
(run (x )
(lol o ((a b)) (c d)) ! x )))
5
25
#t,
since ((a b)) (x c)) (d y))) is a list of lists.
#t,
because null o of a fresh variable always
succeeds and associates the fresh variable,
in this case x , with ().
(()),
since replacing x with the empty list in
((a b)) (c d)) ! x ) transforms it to
((a b)) (c d)) ! ()), which is the same as
((a b)) (c d))).
(()
(())
(() ())
(() () ())
(() () () ())).
Is (e tofu)) a twin?
26
Yes,
because it is a list of two identical values.
27
No,
because e and tofu differ.
31
Is (g g g)) a twin?
28
No,
because it is not a list of two values.
29
Yes,
since both (g g)) and (tofu tofu)) are twins.
30
No,
since (e tofu)) is not a twin.
31
No, it isnt.
(define twins o
(lambda (s)
(fresh (x y)
(cons o x y s)
(cons o x () y))))
Is twins o recursive?
32
#t.
(run (q)
(twins o (tofu tofu)))
( #t q))
33
tofu.
(run (z )
(twins o (z tofu))))
32
34
Chapter 3
35
36
Here it is.
(run (z )
(twins o (z tofu))))
(define twins o
(lambda (s)
(fresh (x )
( (x x ) s))))
37
(define lot o
(lambda (l )
(conde
((null o l ) #s)
((fresh (a)
(car o l a)
(twins o a))
(fresh (d )
(cdr o l d )
(lot o d )))
(else #u))))
What does lot stand for?
What value is associated with z in
38
().
(run (z )
(lot o ((g g)) ! z )))
1
39
33
40
41
(run1 (z )
(lot o ((g g)) ! z )))
42
n)
(()
((
((
((
((
))
)(
0) (
0) (
0
0
(run (r )
(fresh (w x y z )
(lot o ((g g)) (e w ) (x y)) ! z ))
( (w (x y)) z ) r )))
5
34
))
)(
))).
43
44
((g g)) ! ((
)(
)(
))),
))
)(
1) (
45
((e
(e
(e
(e
(e
(
(
(
(
(
0
0
0
0
0
)
0)
0)
)
0
)
0
0
)(
())
(( 1
(( 1
(( 1
(( 1
)(
)))
)(2
)(2
1
)(2
1
1
1
)).
)))
)(3
)(3
2
2
2
3
3
)))
)(4
)))).
Chapter 3
46
47
(run (out)
(fresh (w x y z )
( ((g g)) (e w ) (x y)) ! z ) out)
(lot o out)))
3
Here is listof o .
) ! ((
)(
))),
48
)(
))
)(
)(
0
)(
)).
))
)(
1
))).
))
)(
))).
Yes.
(define listof o
(lambda (pred o l )
(conde
((null o l ) #s)
((fresh (a)
(car o l a)
(pred o a))
(fresh (d )
(cdr o l d )
(listof o pred o d )))
(else #u))))
Is listof o recursive?
49
(run (out)
(fresh (w x y z )
( ((g g)) (e w ) (x y)) ! z ) out)
(listof o twins o out)))
3
50
))
)(
)(
0
Thats simple.
(define lot o
(lambda (l )
(listof o twins o l )))
35
Remember member?
51
(define member?
(lambda (x l )
(cond
((null? l ) #f)
((eq-car? l x ) #t)
(else (member? x (cdr l ))))))
Define eq-car?.
Dont worry. It will make sense soon.
52
Okay.
53
54
(define member o
(lambda (x l )
(conde
((null o l ) #u)
((eq-car o l x ) #s)
(else
(fresh (d )
(cdr o l d )
(member o x d ))))))
(define eq-car
(lambda (l x )
(car o l x )))
o
55
56
57
(run (q)
(member o olive (virgin olive oil)))
( #t q))
36
Yes.
Whenever a conde line is guaranteed to
fail, it is unnecessary.
(member? x (cdr l )).
#t,
because (member o a l ) succeeds, but this
is still uninteresting.
Chapter 3
58
(run (y)
(member o y (hummus with pita))))
1
59
(run1 (y)
(member o y (with pita))))
60
(run (y)
(member o y (pita))))
1
61
(run (y)
(member o y ()))
62
(run (y)
(member o y (hummus with pita))))
63
hummus,
because we can ignore the first conde line
since l is not the empty list, and because
the second conde line associates the fresh
variable y with the value of (car l ), which
is hummus.
with,
because we can ignore the first conde line
since l is not the empty list, and because
the second conde line associates the fresh
variable y with the value of (car l ), which
is with.
pita,
because we can ignore the first conde line
since l is not the empty list, and because
the second conde line associates the fresh
variable y with the value of (car l ), which
is pita.
(),
because the (null o l ) question of the first
conde line now holds, resulting in failure
of the goal (member o y l ).
37
So is the value of
64
Yes.
(run (y)
(member o y l ))
65
66
(define identity
(lambda (l )
(run (y)
(member o y l ))))
e.
(run (x )
(member o e (pasta x fagioli))))
67
(run (x )
(member o e (pasta x fagioli))))
68
69
(run1 (x )
(member o e (pasta e x fagioli))))
38
70
e,
,
because the recursion succeeds before it
gets to the variable x .
Chapter 3
71
((e
)(
e))).
(run (r )
(fresh (x y)
(member o e (pasta x fagioli y)))
( (x y)) r )))
72
73
((tofu !
)).
(run (l )
(member o tofu l ))
1
74
75
It has no value,
because run never finishes building the
list.
76
((tofu ! 0 )
( 0 tofu ! 1 )
( 0 1 tofu ! 2 )
( 0 1 2 tofu ! 3 )
( 0 1 2 3 tofu ! 4 )).
Clearly each list satisfies member o , since
tofu is in every list.
(run (l )
(member o tofu l ))
39
77
78
Perhaps,
but we do know when weve found the
value were looking for.
79
80
(define pmember o
(lambda (x l )
(conde
((null o l ) #u)
((eq-car o l x ) (cdr o l ()))
(else
(fresh (d )
(cdr o l d )
(pmember o x d ))))))
((tofu))
( 0 tofu))
( 0 1 tofu))
( 0 1 2 tofu))
( 0 1 2 3 tofu))).
40
Chapter 3
81
Is it (#t #t))?
(run (q)
(pmember o tofu (a b tofu d tofu)))
( #t q))
82
83
(define pmember o
(lambda (x l )
(conde
((null o l ) #u)
((eq-car o l x ) (cdr o l ()))
((eq-car o l x ) #s)
(else
(fresh (d )
(cdr o l d )
(pmember o x d ))))))
How does this refined definition differ from
the original definition of pmember o
84
Is it (#t #t))?
(run (q)
(pmember o tofu (a b tofu d tofu)))
( #t q))
85
41
86
87
88
(run (q)
(pmember o tofu (a b tofu d tofu)))
( #t q))
42
89
((tofu))
(tofu 0 ! 1 )
( 0 tofu))
( 0 tofu 1 ! 2 )
( 0 1 tofu))
( 0 1 tofu 2 ! 3 )
( 0 1 2 tofu))
( 0 1 2 tofu 3 ! 4 )
( 0 1 2 3 tofu))
( 0 1 2 3 tofu 4 ! 5 )
( 0 1 2 3 4 tofu))
( 0 1 2 3 4 tofu 5 ! 6 )).
Chapter 3
90
91
92
93
94
(run (l )
(pmember o tofu l ))
12
(define pmember o
(lambda (x l )
(conde
((eq-car o l x )
(fresh (a d )
(cdr o l (a ! d ))))
((eq-car o l x ) (cdr o l ()))
(else
(fresh (d )
(cdr o l d )
(pmember o x d ))))))
((tofu 0 ! 1 )
(tofu))
( 0 tofu 1 ! 2 )
( 0 tofu))
( 0 1 tofu 2 ! 3 )
( 0 1 tofu))
( 0 1 2 tofu 3 ! 4 )
( 0 1 2 tofu))
( 0 1 2 3 tofu 4 ! 5 )
( 0 1 2 3 tofu))
( 0 1 2 3 4 tofu 5 ! 6 )
( 0 1 2 3 4 tofu))).
43
95
(define first-value
(lambda (l )
(run1 (y)
(member o y l ))))
96
(pasta)).
97
pasta.
98
(define memberrev o
(lambda (x l )
(conde
((null o l ) #u)
(#s
(fresh (d )
(cdr o l d )
(memberrev o x d )))
(else (eq-car o l x )))))
99
100
(run (x )
(memberrev o x (pasta e fagioli))))
44
Chapter 3
101
Here it is.
(define reverse-list
(lambda (l )
(run (y)
(memberrev o y l ))))
MARMALADE STAINS!
45
Chapter 4
Members Only
(define mem
(lambda (x l )
(cond
((null? l ) #f)
((eq-car? l x ) l )
(else (mem x (cdr l ))))))
What is the value of
(mem tofu (a b tofu d peas e)))
#f.
(run (out)
( (mem tofu (a b tofu d peas e))) out))
(peas e)).
(mem peas
(mem tofu (a b tofu d peas e))))
(mem tofu
(mem tofu (a b tofu d tofu e))))
Members Only
(tofu e)),
because the value of
(mem tofu (a b tofu d tofu e))) is
(tofu d tofu e)), the value of
(cdr (tofu d tofu e))) is (d tofu e)), and the
value of (mem tofu (d tofu e))) is (tofu e)).
47
Here is memo .
(define memo
(lambda (x l out)
(conde
((null o l ) #u)
((eq-car o l x ) ( l out))
(else
(fresh (d )
(cdr o l d )
(memo x d out))))))
10
At most once.
(run (out)
(memo tofu (a b tofu d tofu e)) out))
1
48
11
Chapter 4
12
tofu.
(run (r )
(memo r
(a b tofu d tofu e))
(tofu d tofu e))))
13
(run (q)
(memo tofu (tofu e)) (tofu e)))
( #t q))
14
(run (q)
(memo tofu (tofu e)) (tofu)))
( #t q))
15
(run (x )
(memo tofu (tofu e)) (x e))))
16
(run (x )
(memo tofu (tofu e)) (peas x )))
17
#t,
since (tofu e)), the last argument to memo ,
is the right value.
(),
since (tofu)), the last argument to memo , is
the wrong value.
tofu,
when the value associated with x is tofu,
then (x e)) is (tofu e)).
(),
because there is no value that, when
associated with x , makes (peas x ) be
(tofu e)).
(run (out)
(fresh (x )
(memo tofu (a b x d tofu e)) out)))
Members Only
49
18
s?
0
0
(tofu ! 0 )
( 0 tofu ! 1 )
( 0 1 tofu ! 2 )
( 0 1 2 tofu ! 3 )
( 0 1 2 3 tofu ! 4 )
( 0 1 2 3 4 tofu ! 5 )
( 0 1 2 3 4 5 tofu ! 6 )
( 0 1 2 3 4 5 6 tofu ! 7 )
( 0 1 2 3 4 5 6 7 tofu ! 8 )
( 0 1 2 3 4 5 6 7 8 tofu ! 9 )).
19
20
In order for
(memo tofu (a b tofu d tofu e ! z ) u)
to succeed, there must be a tofu in z . So
memo creates all the possible lists with tofu
as one element of the list. Thats very
interesting!
21
50
Chapter 4
Remember rember.
22
(define rember
(lambda (x l )
(cond
((null? l ) ())
((eq-car? l x ) (cdr l ))
(else
(cons (car l )
(rember x (cdr l )))))))
23
(a b d peas e)).
24
(define rember o
(lambda (x l out)
(conde
((null o l ) ( () out))
((eq-car o l x ) (cdr o l out))
(else
(fresh (res)
(fresh (d )
(cdr o l d )
(rember o x d res))
(fresh (a)
(car o l a)
(cons o a res out)))))))
Is rember o recursive?
Why are there three freshes in
(fresh (res)
(fresh (d )
(cdr o l d )
(rember o x d res))
(fresh (a)
(car o l a)
(cons o a res out)))
Members Only
25
51
Rewrite
26
(fresh (res)
(fresh (d )
(cdr o l d )
(rember o x d res))
(fresh (a)
(car o l a)
(cons o a res out)))
(fresh (a d res)
(cdr o l d )
(rember o x d res)
(car o l a)
(cons o a res out)).
27
28
29
30
(run (out)
(fresh (y)
(rember o peas (a b y d peas e)) out)))
1
52
(fresh (a d res)
(cons o a d l )
(rember o x d res)
(cons o a res out)).
Chapter 4
31
(run (out)
(fresh (y z )
(rember o y (a b y d z e)) out)))
((b a
(a b
(a b
(a b
(a b
(a b
(a b
e))
e))
)
0 e)
)
0 e)
d
e)
)
0
e d 0)
d 1 e))).
0
d
d
d
d
0
0
32
33
34
Why is
35
36
Yes.
37
Why is
38
Why is
(b a d
e))
(a b d
e))
(a b d
e))
e)) is
Members Only
53
39
No,
but the y has been removed.
Why is
40
41
Why is
42
(a b d
e))
(a b
d e))
43
0
44
Why is
(a b e d
45
0
54
46
Chapter 4
47
Why is
(a b
e))
and
48
1
49
(run (r )
(fresh (y z )
(rember o y (y d z e)) (y d e)))
( (y z ) r )))
50
Why is
51
Why is
(d d))
the second value?
succeeds.
52
Why is
0
((d d))
(d d))
( 0 0)
(e e))).
(d d))
How is
(d d))
the first value?
Members Only
53
55
How is
54
55
56
(d d))
the second value?
How is
(
How is
(e e))
the fourth value?
57
(run (w )
(fresh (y z out)
(rember o y (a b y d z ! w ) out)))
13
0
0
0
0
0
()
( 0 ! 1)
( 0)
( 0 1 ! 2)
( 0 1)
( 0 1 2 ! 3)
( 0 1 2)
( 0 1 2 3 ! 4 )).
Why is
0
58
56
Chapter 4
How is
59
60
61
62
63
How is
0
How is
0
How is
()
the sixth value?
How is
(
Members Only
57
64
65
66
Yes.
67
Yes.
All w of the form
How is
( 0)
the eighth value?
How is
(
...
n+1
Here is surprise o .
68
(define surprise o
(lambda (s)
(rember o s (a b c)) (a b c)))))
69
d.
(run (r )
( d r )
(surprise o r ))
58
70
( 0 ).
When r is fresh, (surprise o r ) succeeds
and leaves r fresh.
Chapter 4
71
72
(b)),
which also makes no sense. Please pass the
aspirin!
CARROT STAINS!
Members Only
59
Chapter 5
Here it is.
No.
(a b c d e)).
(define append
(lambda (l s)
(cond
((null? l ) s)
(else (cons (car l )
(append (cdr l ) s))))))
What is the value of
(append (a b c)) (d e)))
(a b c)).
(d e)).
(append () (d e)))
It has no meaning,
because a is neither the empty list nor a
proper list.
(append a (d e)))
61
Define append o .
Ouch.
(define append o
(lambda (l s out)
(conde
((null o l ) ( s out))
(else
(fresh (a d res)
(car o l a)
(cdr o l d )
(append o d s res)
(cons o a res out))))))
10
(run (x )
(append o
(cake))
(tastes yummy))
x ))
11
tastes yummy)).
(run (x )
(fresh (y)
(append o
(cake with ice y))
(tastes yummy))
x )))
12
).
(run (x )
(fresh (y)
(append o
(cake with ice cream))
y
x )))
62
Chapter 5
13
(run (x )
(fresh (y)
(append o (cake with ice ! y)) (d t)) x )))
1
14
By this example
(run1 (y)
(fresh (x )
(append o (cake with ice ! y)) (d t)) x )))
which associates y with the empty list.
15
16
(define append o
(lambda (l s out)
(conde
((null o l ) ( s out))
(else
(fresh (a d res)
(cons o a d l )
(append o d s res)
(cons o a res out))))))
(run (x )
(fresh (y)
(append o (cake with ice ! y)) (d t)) x )))
5
17
((cake
(cake
(cake
(cake
(cake
with
with
with
with
with
ice d t))
ice 0 d t))
ice 0 1 d t))
ice 0 1 2 d t))
ice 0 1 2 3 d t))).
(()
( 0)
( 0 1)
( 0 1 2)
( 0 1 2 3 )).
63
) for y in
18
).
)).
Right. What is
(append (cake with ice
) (d t)))
20
(run (x )
(fresh (y)
(append o
(cake with ice ! y))
(d t ! y))
x )))
5
21
((cake
(cake
(cake
(cake
(cake
with
with
with
with
with
ice d t))
ice 0 d t 0 )
ice 0 1 d t 0 1 )
ice 0 1 2 d t 0 1
ice 0 1 2 3 d t 0
2
1
)
2
)).
)).
(run (x )
(fresh (z )
(append o
(cake with ice cream))
(d t ! z )
x )))
22
23
(run6 (x )
(fresh (y)
(append o x y (cake with ice d t)))))
64
(()
(cake))
(cake with))
(cake with ice))
(cake with ice d))
(cake with ice d t))).
Chapter 5
24
25
(run (y)
(fresh (x )
(append o x y (cake with ice d t)))))
6
26
27
(run6 (r )
(fresh (x y)
(append o x y (cake with ice d t)))
( (x y)) r )))
28
29
It has no value,
since it is still looking for the seventh
value.
30
(run (r )
(fresh (x y)
(append o x y (cake with ice d t)))
( (x y)) r )))
7
65
31
32
(run7 (r )
(fresh (x y)
(append o x y (cake with ice d t)))
( (x y)) r )))
What is the value of
33
(run (x )
(fresh (y z )
(append o x y z )))
7
34
(run (y)
(fresh (x z )
(append o x y z )))
7
(()
( 0)
( 0 1)
( 0 1 2)
( 0 1 2 3)
( 0 1 2 3 4)
( 0 1 2 3 4 5 )).
(
0
0
0
0
0
0
0
66
35
).
Chapter 5
36
(run (z )
(fresh (x y)
(append o x y z )))
7
37
(run7 (r )
(fresh (x y z )
(append o x y z )
( (x y z ) r )))
38
39
(0
( 0 ! 1)
( 0 1 ! 2)
( 0 1 2 ! 3)
( 0 1 2 3 ! 4)
( 0 1 2 3 4 ! 5)
( 0 1 2 3 4 5 ! 6 )).
((() 0 0 )
(( 0 ) 1 ( 0 ! 1 ))
(( 0 1 ) 2 ( 0 1 ! 2 ))
(( 0 1 2 ) 3 ( 0 1 2 ! 3 ))
(( 0 1 2 3 ) 4 ( 0 1 2 3 ! 4 ))
(( 0 1 2 3 4 ) 5 ( 0 1 2 3 4 ! 5 ))
(( 0 1 2 3 4 5 ) 6 ( 0 1 2 3 4 5 !
))).
Thats a snap.
(define swappend o
(lambda (l s out)
(conde
(#s
(fresh (a d res)
(cons o a d l )
(cons o a res out)
(swappend o d s res)))
(else (null o l ) ( s out)))))
It has no value.
(run (z )
(fresh (x y)
(swappend o x y z )))
1
67
Why does
40
(run1 (z )
(fresh (x y)
(swappend o x y z )))
have no value?
(define-syntax lambda-limited
(syntax-rules ()
(( n formals g)
(let ((x (var x)))
(lambda formals
(ll n x g))))))
(define swappend o
(lambda-limited 5 (l s out)
(conde
(#s
(fresh (a d res)
(cons o a d l)
(cons o a res out)
(swappend o d s res)))
(else (null o l) ( s out)))))
(define ll
(lambda (n x g)
(G (s)
(let ((v (walk x s)))
(cond
((var? v ) (g (ext-s x 1 s)))
((< v n) (g (ext-s x (+ v 1) s)))
(else (#u s)))))))
The functions var, walk, and ext-s are described in 9:6, 9:27,
and 9:29, respectively. G (see appendix) is just lambda.
41
pizza.
(define unwrap
(lambda (x )
(cond
((pair? x ) (unwrap (car x )))
(else x ))))
What is the value of
(unwrap ((((pizza))))))
42
pizza.
43
Good idea.
44
Not too.
68
Chapter 5
Define unwrap o .
45
46
(run (x )
(unwrap o (((pizza)))) x ))
(pizza
(pizza))
((pizza)))
(((pizza))))).
47
48
It has no value.
49
It has no value.
50
51
(run (x )
(unwrap o x pizza))
1
Why doesnt
(run (x )
(unwrap o ((x )) pizza))
1
have a value?
What can we do about that?
69
52
53
(define unwrap o
(lambda (x out)
(conde
(#s ( x out))
(else
(fresh (a)
(car o x a)
(unwrap o a out))))))
(run (x )
(unwrap o x pizza))
5
54
(run5 (x )
(unwrap o x ((pizza)))))
Like this.
55
(run (x )
(unwrap o ((x )) pizza))
5
(pizza
(pizza ! 0 )
((pizza ! 0 ) ! 1 )
(((pizza ! 0 ) ! 1 ) ! 2 )
((((pizza ! 0 ) ! 1 ) ! 2 ) !
)).
(((pizza)))
(((pizza))) ! 0 )
((((pizza))) ! 0 ) ! 1 )
(((((pizza))) ! 0 ) ! 1 ) ! 2 )
((((((pizza))) ! 0 ) ! 1 ) ! 2 ) !
(pizza
(pizza ! 0 )
((pizza ! 0 ) ! 1 )
(((pizza ! 0 ) ! 1 ) ! 2 )
((((pizza ! 0 ) ! 1 ) ! 2 ) !
56
Okay, okay!
57
Indubitably!
70
)).
)).
Chapter 5
58
(a b c)).
(define flatten
(lambda (s)
(cond
((null? s) ())
((pair? s)
(append
(flatten (car s))
(flatten (cdr s))))
(else (cons s ())))))
What is the value of
(flatten ((a b)) c)))
Define flatten o .
59
Here it is.
(define flatten o
(lambda (s out)
(conde
((null o s) ( () out))
((pair o s)
(fresh (a d res-a res-d )
(cons o a d s)
(flatten o a res-a)
(flatten o d res-d )
(append o res-a res-d out)))
(else (cons o s () out)))))
60
(run (x )
(flatten o ((a b)) c)) x ))
1
61
See 4:27.
(a b c)).
No surprises here.
(a b c)).
(run (x )
(flatten o (a (b c))) x ))
1
71
62
(run (x )
(flatten o (a)) x ))
63
64
(run (x )
(flatten o ((a))) x ))
65
66
(run (x )
(flatten o (((a)))) x ))
72
((a))
(a ())
((a)))).
Here is a surprise!
((a))
(a ())
(a ())
(a () ())
((a)))
((a)) ())
(((a))))).
((a))
(a ())
(a ())
(a () ())
(a ())
(a () ())
(a () ())
(a () () ())
((a)))
((a)) ())
((a)) ())
((a)) () ())
(((a))))
(((a))) ())
((((a)))))).
Chapter 5
67
68
(run (x )
(flatten o ((a b)) c)) x ))
((a b c))
(a b c ())
(a b (c)))
(a b () c))
(a b () c ())
(a b () (c)))
(a (b)) c))
(a (b)) c ())
(a (b)) (c)))
((a b)) c))
((a b)) c ())
((a b)) (c)))
(((a b)) c)))).
69
70
71
It has no value.
72
(run (x )
(flatten o x (a b c))))
73
73
(define flattenrev o
(lambda (s out)
(conde
(#s (cons o s () out))
((null o s) ( () out))
(else
(fresh (a d res-a res-d )
(cons o a d s)
(flattenrev o a res-a)
(flattenrev o d res-d )
(append o res-a res-d out))))))
74
75
(run (x )
(flattenrev o ((a b)) c)) x ))
76
(reverse
(run (x )
(flattenrev o ((a b)) c)) x )))
74
Chapter 5
77
((a b ! c))
(a b c))).
78
79
It has no value.
In fact, it is still trying to determine the
third value.
(run (x )
(flattenrev o x (a b c))))
2
80
574.
Wow!
CHUTNEY STAINS!
75
Chapter 6
Yes.
Yes.
No,
because although the question of the first
conde line within any o fails, the answer of
the second conde line, (any o #u), is where
we started.
(run (q)
never o
( #t q))
1
(run1 (q)
#u
never o )
Here is a useful definition.
(),
because #u fails before never o is reached.
#t.
77
It has no value,
since run never finishes building the list
(#t #t #t ...
(run (q)
always o
( #t q))
10
(#t #t #t #t #t)).
(run (q)
always o
( #t q))
5
11
(run5 (q)
( #t q)
always o )
12
No.
(define sal o
(lambda (g)
(conde
(#s #s)
(else g))))
Is sal o recursive?
78
13
(#t)),
because the first conde line of sal o
succeeds.
Chapter 6
14
(run (q)
(sal o never o )
( #t q))
1
15
It has no value,
because run never finishes determining
the second value.
16
It has no value,
because when the #u occurs, we pretend
that the first conde line of sal o fails,
which causes conde to try never o , which
neither succeeds nor fails.
17
It has no value,
because always o succeeds, followed by #u,
which causes always o to be retried, which
succeeds again, which leads to #u again,
which causes always o to be retried again,
which succeeds again, which leads to #u,
etc.
18
It has no value.
First, #f gets associated with q, then
always o succeeds once. But in the outer
( #t q) we cant associate #t with q since
q is already associated with #f. So the
outer ( #t q) fails, then always o succeeds
again, and then ( #t q) fails again, etc.
(run (q)
(sal o never o )
( #t q))
(#t)),
because the first conde line of sal o
succeeds.
79
19
(run1 (q)
(condi
(( #f q) always o )
(else ( #t q)))
( #t q))
(#t)),
because after the first failure, instead of
staying on the first line we try the second
condi line.
20
It has no value,
since the second condi line is out of values.
21
(run (q)
(condi
(( #f q) always o )
(else ( #t q)))
( #t q))
2
(#t #t #t #t #t)).
always o succeeds five times, but
contributes none of the five values, since
then #f would be in the list.
(run (q)
(condi
(( #f q) always o )
(else (any o ( #t q))))
( #t q))
5
80
22
23
Chapter 6
24
(tea #f cup)).
(run (r )
(condi
((teacup o r ) #s)
(( #f r ) #s)
(else #u)))
5
See 1:56.
25
(#t #t #t #t #t)).
(run5 (q)
(condi
(( #f q) always o )
(( #t q) always o )
(else #u))
( #t q))
26
No,
then the expression has no value.
27
It has no value,
because the first conde line succeeds, but
the outer ( #t q) fails. This causes the
first conde line to succeed again, etc.
have no value?
81
28
It is (#t #t #t #t #t)).
(run (q)
(conde
(always o #s)
(else never o ))
( #t q))
5
29
No.
30
It has no value,
because after the first condi line succeeds,
rather than staying on the same condi
line, it tries for more values on the second
condi line, but that line is never o .
31
It has no value.
First, #f is associated with q. Then
always o , the second goal of the all
expression, succeeds, so the entire all
expression succeeds. Then ( #t q) tries to
associate a value that is different from #f
with q. This fails. So always o succeeds
again, and once again the second goal,
( #t q), fails. Since always o always
succeeds, there is no value.
(run (q)
(condi
(always o #s)
(else never o ))
( #t q))
5
82
Chapter 6
32
(run1 (q)
(alli
(conde
(( #f q) #s)
(else ( #t q)))
always o )
( #t q))
(#t)).
First, #f is associated with q. Then,
always o succeeds. Then the outer goal
( #t q) fails. This time, however, alli
moves on to the second conde line and
associates #t with q. Then always o
succeeds, as does the outer ( #t q).
33
(run (q)
(alli
(conde
(( #f q) #s)
(else ( #t q)))
always o )
( #t q))
5
34
(#t #t #t #t #t)).
always o succeeds ten times, with the value
associated with q alternating between #f
and #t.
(run (q)
(alli
(conde
(( #t q) #s)
(else ( #f q)))
always o )
( #t q))
5
35
83
36
(#t #t #t #t #t)).
(run5 (q)
(all
(conde
(#s #s)
(else never o ))
always o )
( #t q))
Why does
37
No,
it has no value.
38
It has no value,
because the first conde line succeeds, and
the outer ( #t q) succeeds. This yields
one value, but when we go for a second
value, we reach never o .
39
Yes,
since none of the conde lines contribute
more than one value.
(run (q)
(alli
(conde
(#s #s)
(else never o ))
always o )
( #t q))
5
have no value?
84
Chapter 6
This is
A BREAK
85
Chapter 7
Is 0 a bit?
Yes.
Is 1 a bit?
Yes.
Is 2 a bit?
No.
A bit is either a 0 or a 1.
0 and 1.
(define bit-xor o
(lambda (x y r )
(conde
(( 0 x ) ( 0
(( 1 x ) ( 0
(( 0 x ) ( 1
(( 1 x ) ( 1
(else #u))))
y)
y)
y)
y)
(
(
(
(
0
1
1
0
r ))
r ))
r ))
r ))
(define bit-xor o
(lambda (x y r )
(fresh (s t u)
(bit-nand o x
(bit-nand o x
(bit-nand o s
(bit-nand o t
y
s
y
u
s)
t)
u)
r ))))
where bit-nand o is
(define bit-nand o
(lambda (x y r )
(conde
(( 0 x ) (
(( 1 x ) (
(( 0 x ) (
(( 1 x ) (
(else #u))))
0
0
1
1
y)
y)
y)
y)
(
(
(
(
1
1
1
0
r ))
r ))
r ))
r ))
(run (s)
(fresh (x y)
(bit-xor o x y 0)
( (x y)) s)))
which has the value
((0 0))
(1 1))).
87
(run (s)
(fresh (x y)
(bit-xor o x y 1)
( (x y)) s)))
which has the value
((1 0))
(0 1))).
y)
y)
y)
y)
(
(
(
(
0
0
0
1
10
((0
(1
(0
(1
0
0
1
1
0))
1))
1))
0))).
r ))
r ))
r ))
r ))
(define bit-and o
(lambda (x y r )
(fresh (s)
(bit-nand o x y s)
(bit-not o s r ))))
where bit-not o itself is defined in terms of bit-nand o
(define bit-not o
(lambda (x r )
(bit-nand o x x r )))
11
(run (s)
(fresh (x y)
(bit-and o x y 1)
( (x y)) s)))
which has the value
((1 1))).
88
Chapter 7
12
(define half-adder o
(lambda (x y r c)
(all
(bit-xor o x y r )
(bit-and o x y c))))
(run (r )
(half-adder o 1 1 r 1))
13
(run (s)
(fresh (x y r c)
(half-adder o x y r c)
( (x y r c)) s)))
Describe half-adder o .
14
Here is full-adder o .
15
(define full-adder o
(lambda (b x y r c)
(fresh (w xy wz )
(half-adder o x y w xy)
(half-adder o w b r wz )
(bit-xor o xy wz c))))
The x , y, r , and c variables serve the same
purpose as in half-adder o . full-adder o also
takes a carry-in bit, b. What value is
associated with s in
(run (s)
(fresh (r c)
(full-adder o 0 1 1 r c)
( (r c)) s)))
(define half-adder o
(lambda (x y r c)
(conde
(( 0 x ) ( 0
(( 1 x ) ( 0
(( 0 x ) ( 1
(( 1 x ) ( 1
(else #u))))
0.
((0
(1
(0
(1
0
0
1
1
0
1
1
0
y)
y)
y)
y)
(
(
(
(
0
1
1
0
r)
r)
r)
r)
(
(
(
(
0
0
0
1
c))
c))
c))
c))
0))
0))
0))
1))).
(define full-adder o
(lambda (b x y r c)
(conde
(( 0 b) ( 0 x )
(( 1 b) ( 0 x )
(( 0 b) ( 1 x )
(( 1 b) ( 1 x )
(( 0 b) ( 0 x )
(( 1 b) ( 0 x )
(( 0 b) ( 1 x )
(( 1 b) ( 1 x )
(else #u))))
(
(
(
(
(
(
(
(
0
0
0
0
1
1
1
1
y)
y)
y)
y)
y)
y)
y)
y)
(
(
(
(
(
(
(
(
0
1
1
0
1
0
0
1
r)
r)
r)
r)
r)
r)
r)
r)
(
(
(
(
(
(
(
(
0
0
0
1
0
1
1
1
c))
c))
c))
c))
c))
c))
c))
c))
89
16
(1 1)).
(run (s)
(fresh (r c)
(full-adder o 1 1 1 r c)
( (r c)) s)))
17
(run (s)
(fresh (b x y r c)
(full-adder o b x y r c)
( (b x y r c)) s)))
((0
(1
(0
(1
(0
(1
(0
(1
0
0
1
1
0
0
1
1
0
0
0
0
1
1
1
1
0
1
1
0
1
0
0
1
0))
0))
0))
1))
0))
1))
1))
1))).
Describe full-adder o .
18
What is a number ?
19
20
No.
Each number is represented as a list of
bits.
21
22
90
23
(0))?
No.
Each number is represented uniquely,
therefore (0)) cannot also represent the
number zero.
Chapter 7
24
25
(1)),
because the value of (1)) is 1 20 , which is
the number one.
5,
(1 0 1))
26
(1 1 1))
27
28
29
30
How do we represent 19
31
32
7,
(1 0 0 1)),
because the value of (1 0 0 1)) is
1 20 + 0 21 + 0 22 + 1 23 , which is the
same as 1 + 0 + 0 + 8, which is nine.
91
33
34
35
36
37
38
39
40
(0 ! n)) is twice n.
But n cannot be (), since (0 ! n)) is (0)),
which does not represent a number.
(0 1 0 1)),
since twice five is ten.
(1 1 0 1)),
since one more than twice five is eleven.
().
(build-num 0)
41
(0 0 1 0 0 1)).
(build-num 36)
42
(1 1 0 0 1)).
(build-num 19)
92
Chapter 7
Define build-num.
43
44
Thats easy.
(define build-num
(lambda (n)
(cond
((odd? n)
(cons 1
(build-num ( ( n 1) 2))))
((and (not (zero? n)) (even? n))
(cons 0
(build-num ( n 2))))
((zero? n) ()))))
45
46
Yes.
This is called the non-overlapping
property. It appears rather frequently
throughout this and the next chapter.
93
47
48
49
50
51
52
53
54
Two,
which is represented by (0 1)).
55
Three,
which is represented by (1 1)).
56
57
(x 1))
94
Chapter 7
58
59
60
61
One,
which is represented by (1)), since (0)) does
not represent a number.
62
63
64
One,
since (1 ! ()) is (1)).
65
Three,
since (1 ! (1))) is (1 1)).
(1 ! z )
95
66
Five,
since (1 ! (0 1))) is (1 0 1)).
67
68
(1 ! z )
where z is (0 1))
69
70
71
Yes.
72
73
74
(0 ! z )
represent numbers?
(0 0 ! z )
96
Chapter 7
75
76
77
78
79
(0 y ! z )
80
#t.
(define pos o
(lambda (n)
(fresh (a d )
( (a ! d ) n))))
What value is associated with q in
(run (q)
(pos o (0 1 1)))
( #t q))
81
#t.
(run (q)
(pos o (1)))
( #t q))
97
82
().
(run (q)
(pos o ())
( #t q))
83
).
(run (r )
(pos o r ))
84
Yes.
85
(x y ! z )
86
#t.
(define >1o
(lambda (n)
(fresh (a ad dd )
( (a ad ! dd ) n))))
What value is associated with q in
(run (q)
(>1o (0 1 1)))
( #t q))
87
(#t)).
(run (q)
(>1o (0 1)))
( #t q))
98
Chapter 7
88
().
(run (q)
(>1o (1)))
( #t q))
89
().
(run (q)
(>1o ())
( #t q))
90
).
(run (r )
(>1o r ))
91
92
Yes.
(0 1 1)).
(0 1 1))
93
(0 x 1 0 y ! z )
94
(0 0 y ! z )
95
(0 x 1)),
since everything to the right of the
rightmost 1 is ignored.
(),
since there is no rightmost 1.
().
99
96
97
Is (
()
) a ground value?
(( 0 () 0 )
(() ( 0 ! 1 ) ( 0 ! 1 ))
((1)) (1)) (0 1)))).
(adder o 0 x y r ) sums x and y to produce
r . For example, in the first value, zero
added to a number is the number. In the
second value, the sum of () and ( 0 ! 1 ) is
( 0 ! 1 ). In other words, the sum of zero
and a positive number is the positive
number.
98
Yes.
99
No,
because it contains one or more variables.
100
100
Chapter 7
101
(run (s)
(fresh (x y r )
(adder o 0 x y r )
( (x y r ) s)))
22
102
103
(( 0 () 0 )
(() ( 0 ! 1 ) ( 0 ! 1 ))
((1)) (1)) (0 1)))
((1)) (0 0 ! 1 ) (1 0 ! 1 ))
((0 0 ! 1 ) (1)) (1 0 ! 1 ))
((1)) (1 1)) (0 0 1)))
((0 1)) (0 1)) (0 0 1)))
((1)) (1 0 0 ! 1 ) (0 1 0 ! 1 ))
((1 1)) (1)) (0 0 1)))
((1)) (1 1 1)) (0 0 0 1)))
((1 1)) (0 1)) (1 0 1)))
((1)) (1 1 0 0 ! 1 ) (0 0 1 0 ! 1 ))
((1 0 0 ! 1 ) (1)) (0 1 0 ! 1 ))
((1)) (1 1 1 1)) (0 0 0 0 1)))
((0 1)) (0 0 0 ! 1 ) (0 1 0 ! 1 ))
((1)) (1 1 1 0 0 ! 1 ) (0 0 0 1 0 ! 1 ))
((1 1 1)) (1)) (0 0 0 1)))
((1)) (1 1 1 1 1)) (0 0 0 0 0 1)))
((0 1)) (1 1)) (1 0 1)))
((1)) (1 1 1 1 0 0 ! 1 ) (0 0 0 0 1 0 ! 1 ))
((1 1 0 0 ! 1 ) (1)) (0 0 1 0 ! 1 ))
((1)) (1 1 1 1 1 1)) (0 0 0 0 0 0 1)))).
(( 0 () 0 )
(() ( 0 ! 1 ) ( 0 ! 1 ))
((1)) (0 0 ! 1 ) (1 0 ! 1 ))
((0 0 ! 1 ) (1)) (1 0 ! 1 ))
((1)) (1 0 0 ! 1 ) (0 1 0 ! 1 ))
((1)) (1 1 0 0 ! 1 ) (0 0 1 0 ! 1 ))
((1 0 0 ! 1 ) (1)) (0 1 0 ! 1 ))
((0 1)) (0 0 0 ! 1 ) (0 1 0 ! 1 ))
((1)) (1 1 1 0 0 ! 1 ) (0 0 0 1 0 ! 1 ))
((1)) (1 1 1 1 0 0 ! 1 ) (0 0 0 0 1 0 ! 1 ))
((1 1 0 0 ! 1 ) (1)) (0 0 1 0 ! 1 ))).
101
104
105
106
107
108
Huh?
109
Almost,
since x + y = y + x.
110
No.
For example, the first two values do not
correspond to any other values.
102
Chapter 7
111
112
113
114
115
116
103
117
118
A carry bit.
(define adder o
(lambda (d n m r )
(condi
(( 0 d ) ( () m) ( n r ))
(( 0 d ) ( () n) ( m r )
(pos o m))
(( 1 d ) ( () m)
(adder o 0 n (1)) r ))
(( 1 d ) ( () n) (pos o m)
(adder o 0 (1)) m r ))
(( (1)) n) ( (1)) m)
(fresh (a c)
( (a c)) r )
(full-adder o d 1 1 a c)))
(( (1)) n) (gen-adder o d n m r ))
(( (1)) m) (>1o n) (>1o r )
(adder o d (1)) n r ))
((>1o n) (gen-adder o d n m r ))
(else #u))))
(define gen-adder o
(lambda (d n m r )
(fresh (a b c e x y z )
( (a ! x ) n)
( (b ! y)) m) (pos o y)
( (c ! z ) r ) (pos o z )
(alli
(full-adder o d a b c e)
(adder o e x y z )))))
What is d
104
119
Chapter 7
120
(0 1 0 1)).
(run (s)
(gen-adder o 1 (0 1 1)) (1 1)) s))
121
122
123
124
Describe gen-adder o .
125
126
(run (s)
(fresh (x y)
(adder o 0 x y (1 0 1)))
( (x y)) s)))
127
105
128
(define +o
(lambda (n m k )
(adder o 0 n m k )))
(run (s)
(fresh (x y)
(+o x y (1 0 1)))
( (x y)) s))).
129
(run (s)
(fresh (x y)
(+o x y (1 0 1)))
( (x y)) s)))
130
That is easy.
(define o
(lambda (n m k )
(+o m k n)))
131
((1 1))).
(run (q)
(o (0 0 0 1)) (1 0 1)) q))
132
(()).
(run (q)
(o (0 1 1)) (0 1 1)) q))
133
().
Eight cannot be subtracted from six, since
we do not represent negative numbers.
Chapter 7
107
Chapter 8
(run (t)
(fresh (x y r )
(o x y r )
( (x y r ) t)))
34
((() 0 ())
(( 0 ! 1 ) () ())
((1)) ( 0 ! 1 ) ( 0 ! 1 ))
(( 0 1 ! 2 ) (1)) ( 0 1 ! 2 ))
((0 1)) ( 0 1 ! 2 ) (0 0 1 ! 2 ))
((1 0 ! 1 ) (0 1)) (0 1 0 ! 1 ))
((0 0 1)) ( 0 1 ! 2 ) (0 0 0 1 ! 2 ))
((1 1)) (1 1)) (1 0 0 1)))
((0 1 0 ! 1 ) (0 1)) (0 0 1 0 ! 1 ))
((1 0 ! 1 ) (0 0 1)) (0 0 1 0 ! 1 ))
((0 0 0 1)) ( 0 1 ! 2 ) (0 0 0 0 1 ! 2 ))
((1 1)) (1 0 1)) (1 1 1 1)))
((0 1 1)) (1 1)) (0 1 0 0 1)))
((1 1)) (0 1 1)) (0 1 0 0 1)))
((0 0 1 0 ! 1 ) (0 1)) (0 0 0 1 0 ! 1 ))
((1 1)) (1 1 1)) (1 0 1 0 1)))
((0 1 0 ! 1 ) (0 0 1)) (0 0 0 1 0 ! 1 ))
((1 0 ! 1 ) (0 0 0 1)) (0 0 0 1 0 ! 1 ))
((0 0 0 0 1)) ( 0 1 ! 2 ) (0 0 0 0 0 1 ! 2 ))
((1 0 1)) (1 1)) (1 1 1 1)))
((0 1 1)) (1 0 1)) (0 1 1 1 1)))
((1 0 1)) (0 1 1)) (0 1 1 1 1)))
((0 0 1 1)) (1 1)) (0 0 1 0 0 1)))
((1 1)) (1 0 0 1)) (1 1 0 1 1)))
((0 1 1)) (0 1 1)) (0 0 1 0 0 1)))
((1 1)) (0 0 1 1)) (0 0 1 0 0 1)))
((0 0 0 1 0 ! 1 ) (0 1)) (0 0 0 0 1 0 ! 1 ))
((1 1)) (1 1 0 1)) (1 0 0 0 0 1)))
((0 1 1)) (1 1 1)) (0 1 0 1 0 1)))
((1 1 1)) (0 1 1)) (0 1 0 1 0 1)))
((0 0 1 0 ! 1 ) (0 0 1)) (0 0 0 0 1 0 ! 1 ))
((1 1)) (1 0 1 1)) (1 1 1 0 0 1)))
((0 1 0 ! 1 ) (0 0 0 1)) (0 0 0 0 1 0 ! 1 ))
((1 0 ! 1 ) (0 0 0 0 1)) (0 0 0 0 1 0 ! 1 ))).
Yes,
thanks.
109
(run (p)
(o (0 1)) (0 0 1)) p))
((() 0 ())
(( 0 ! 1 ) () ())
((1)) ( 0 ! 1 ) ( 0 ! 1 ))
(( 0 1 ! 2 ) (1)) ( 0 1 ! 2 ))
((0 1)) ( 0 1 ! 2 ) (0 0 1 ! 2 ))
((1 0 ! 1 ) (0 1)) (0 1 0 ! 1 ))
((0 0 1)) ( 0 1 ! 2 ) (0 0 0 1 ! 2 ))
((0 1 0 ! 1 ) (0 1)) (0 0 1 0 ! 1 ))
((1 0 ! 1 ) (0 0 1)) (0 0 1 0 ! 1 ))
((0 0 0 1)) ( 0 1 ! 2 ) (0 0 0 0 1 ! 2 ))
((0 0 1 0 ! 1 ) (0 1)) (0 0 0 1 0 ! 1 ))
((0 1 0 ! 1 ) (0 0 1)) (0 0 0 1 0 ! 1 ))
((1 0 ! 1 ) (0 0 0 1)) (0 0 0 1 0 ! 1 ))
((0 0 0 0 1)) ( 0 1 ! 2 ) (0 0 0 0 0 1 ! 2 ))
((0 0 0 1 0 ! 1 ) (0 1)) (0 0 0 0 1 0 ! 1 ))
((0 0 1 0 ! 1 ) (0 0 1)) (0 0 0 0 1 0 ! 1 ))
((0 1 0 ! 1 ) (0 0 0 1)) (0 0 0 0 1 0 ! 1 ))
((1 0 ! 1 ) (0 0 0 0 1)) (0 0 0 0 1 0 ! 1 ))).
The fifth nonground value
((0 1)) (
) (0
)).
It is even,
since the first bit of (0 1
Is the product of (1
even?
110
) is 0.
No.
Chapter 8
Yes,
the first ground value
((1 1)) (1 1)) (1 0 0 1)))
shows that the product of three and three
is nine.
10
(define o
(lambda (n m p)
(condi
(( () n) ( () p))
((pos o n) ( () m) ( () p))
(( (1)) n) (pos o m) ( m p))
((>1o n) ( (1)) m) ( n p))
((fresh (x z )
( (0 ! x ) n) (pos o x )
( (0 ! z ) p) (pos o z )
(>1o m)
(o x m z )))
((fresh (x y)
( (1 ! x ) n) (pos o x )
( (0 ! y)) m) (pos o y)
(o m n p)))
((fresh (x y)
( (1 ! x ) n) (pos o x )
( (1 ! y)) m) (pos o y)
(odd-o x n m p)))
(else #u))))
11
12
13
14
15
Here is odd-o .
(define odd-o
(lambda (x n m p)
(fresh (q)
(bound-o q p n m)
(o x m q)
(+o (0 ! q)) m p))))
16
17
18
We know that x is n1
2 . Therefore,
m)
+ m.
n m = 2 ( n1
2
112
Chapter 8
19
(define bound-o
(lambda (q p n m)
#s))
20
(run1 (t)
(fresh (n m)
(o n m (1)))
( (n m)) t)))
((1)) (1))).
This value is contributed by the third
condi line of o .
21
22
Clearly.
(run (t)
(fresh (n m)
(o n m (1)))
( (n m)) t)))
2
Here is bound-o .
(define bound-o
(lambda (q p n m)
(conde
((null o q) (pair o p))
(else
(fresh (x y z )
(cdr o q x )
(cdr o p y)
(condi
((null o n)
(cdr o m z )
(bound-o x y z ()))
(else
(cdr o n z )
(bound-o x y z m))))))))
Is this definition recursive?
113
23
(run (t)
(fresh (n m)
(o n m (1)))
( (n m)) t)))
2
24
(run (p)
(o (1 1 1)) (1 1 1 1 1 1)) p))
If we replace a 1 by a 0 in
(1 0 0 1 1 1 0 1 1)),
which contains nine bits.
25
Yes,
because (1 1 1)) and (1 1 1 1 1 1)) represent
the largest numbers of lengths three and
six, respectively. Of course the rightmost 1
in each number cannot be replaced by a 0.
26
Yes, it is.
(((1)) (1)))),
because bound-o fails when the product of
n and m is larger than p, and since the
length of n plus the length of m is an
upper bound on the length of p.
(define =l o
(lambda (n m)
(conde
(( () n) ( () m))
(( (1)) n) ( (1)) m))
(else
(fresh (a x b y)
( (a ! x ) n) (pos o x )
( (b ! y)) m) (pos o y)
(=l o x y))))))
Is this definition recursive?
114
27
( 2 1))),
1
since y is ( 2 1)), the length of (1 w x ! y))
is the same as the length of (0 1 1 0 1)).
Chapter 8
28
1,
(run (b)
(=l o (1)) (b))))
29
(run (n)
(=l o (1 0 1 ! n)) (0 1 1 0 1))))
30
(run (t)
(fresh (y z )
(=l o (1 ! y)) (1 ! z ))
( (y z ) t)))
5
31
(run (t)
(fresh (y z )
(=l o (1 ! y)) (0 ! z ))
( (y z ) t)))
1)),
because if n were ( 0 1)), then the length of
(1 0 1 ! n)) would be the same as the
length of (0 1 1 0 1)).
((() ())
((1)) (1)))
(( 0 1)) ( 1 1)))
(( 0 1 1)) ( 2 3 1)))
(( 0 1 2 1)) ( 3 4 5 1)))),
because each y and z must be the same
length in order for (1 ! y)) and (1 ! z ) to
be the same length.
32
33
(((1)) (1)))
(( 0 1)) ( 1 1)))
(( 0 1 1)) ( 2 3 1)))
(( 0 1 2 1)) ( 3 4 5 1)))
(( 0 1 2 3 1)) ( 4 5 6 7 1)))).
115
34
(define <l o
(lambda (n m)
(conde
(( () n) (pos o m))
(( (1)) n) (>1o m))
(else
(fresh (a x b y)
( (a ! x ) n) (pos o x )
( (b ! y)) m) (pos o y)
(<l o x y))))))
35
(run (t)
(fresh (y z )
(<l o (1 ! y)) (0 1 1 0 1 ! z ))
( (y z ) t)))
8
((() 0 )
((1)) 0 )
(( 0 1)) 1 )
(( 0 1 1)) 2 )
(( 0 1 2 1)) ( 3 ! 4 ))
(( 0 1 2 3 1)) ( 4 5 ! 6 ))
(( 0 1 2 3 4 1)) ( 5 6 7 ! 8 ))
(( 0 1 2 3 4 5 1)) ( 6 7 8 9 !
10
))).
36
37
It has no value.
Clearly the first two conde lines fail. In
the recursive call, x and y are associated
with the same fresh variable, which is
where we started.
(run (n)
(<l o n n))
1
116
Chapter 8
38
Is this correct?
(define !l o
(lambda (n m)
(conde
((=l o n m) #s)
((<l o n m) #s)
(else #u))))
39
(run8 (t)
(fresh (n m)
(!l o n m)
( (n m)) t)))
40
((() ())
((1)) (1)))
(( 0 1)) ( 1 1)))
(( 0 1 1)) ( 2 3 1)))
(( 0 1 2 1)) ( 3 4 5 1)))
(( 0 1 2 3 1)) ( 4 5 6 7 1)))
(( 0 1 2 3 4 1)) ( 5 6 7 8 9 1)))
(( 0 1 2 3 4 5 1)) ( 6 7 8 9 10
11
1))))
(() ()).
(run (t)
(fresh (n m)
(!l o n m)
(o n (0 1)) m)
( (n m)) t)))
1
41
It has no value,
because the first conde line of !l o always
succeeds, which means that n and m are
always the same length. Therefore
(o n (0 1)) m) succeeds only when n is ().
117
42
(run2 (t)
(fresh (n m)
(!l o n m)
(o n (0 1)) m)
( (n m)) t)))
(define !l o
(lambda (n m)
(condi
((=l o n m) #s)
((<l o n m) #s)
(else #u))))
has a value?
43
(run (t)
(fresh (n m)
(!l o n m)
(o n (0 1)) m)
( (n m)) t)))
10
44
(run (t)
(fresh (n m)
(!l o n m)
( (n m)) t)))
15
118
45
((() ())
((1)) (0 1)))
((0 1)) (0 0 1)))
((1 1)) (0 1 1)))
((0 0 1)) (0 0 0 1)))
((1 0 1)) (0 1 0 1)))
((0 1 1)) (0 0 1 1)))
((0 0 0 1)) (0 0 0 0 1)))
((1 0 1 1)) (0 1 0 1 1)))
((0 1 0 1)) (0 0 1 0 1)))).
((() ())
(() ( 0 " 1 ))
((1)) (1)))
((1)) ( 0 1 " 2 ))
(( 0 1)) ( 1 1)))
(( 0 1)) ( 1 2 3 " 4 ))
(( 0 1 1)) ( 2 3 1)))
(( 0 1 1)) ( 2 3 4 5 " 6 ))
(( 0 1 2 1)) ( 3 4 5 1)))
(( 0 1 2 1)) ( 3 4 5 6 7 " 8 ))
(( 0 1 2 3 1)) ( 4 5 6 7 1)))
(( 0 1 2 3 1)) ( 4 5 6 7 8 9 " 10 ))
(( 0 1 2 3 4 1)) ( 5 6 7 8 9 1)))
(( 0 1 2 3 4 1)) ( 5 6 7 8 9 10 11 " 12 ))
(( 0 1 2 3 4 5 1)) ( 6 7 8 9 10 11 1)))).
Yes.
Chapter 8
46
(define <o
(lambda (n m)
(condi
((<l o n m) #s)
((=l o n m)
(fresh (x )
(pos o x )
(+o n x m)))
(else #u))))
That is easy.
(define !o
(lambda (n m)
(condi
(( n m) #s)
((<o n m) #s)
(else #u))))
47
(run (q)
(<o (1 0 1)) (1 1 1)))
( #t q))
48
(run (q)
(<o (1 1 1)) (1 0 1)))
( #t q))
49
(run (q)
(<o (1 0 1)) (1 0 1)))
( #t q))
50
(run6 (n)
(<o n (1 0 1))))
51
#t,
since five is less than seven.
(),
since seven is not less than five.
(),
since five is not less than five. But if we
were to replace <o with !o , the value
would be (#t)).
((
"
) (0 1 1)) (1 1 1))),
since ( 0 1 2 3 " 4 ) represents all the
numbers greater than seven.
0
119
52
It has no value,
since <o calls <l o .
53
((() ( 0 ! 1 ) () ())
((1)) (1)) (1)) ())
((0 1)) (1 1)) () (0 1)))
((0 1)) (1)) (0 1)) ())
((1)) ( 0 1 ! 2 ) () (1)))
(( 0 1)) ( 0 1)) (1)) ())
((0 0 1)) (1 0 1)) () (0 0 1)))
((0 0 1)) ( 0 1)) (0 1)) ())
(( 0 1)) ( 1 2 3 ! 4 ) () ( 0 1)))
((1 1)) (0 1)) (1)) (1)))
((0 0 1)) (0 1 1)) () (0 0 1)))
((1 1)) (1)) (1 1)) ())
(( 0 1 1)) ( 2 3 4 5 ! 6 ) () ( 0
(( 0 1 1)) ( 0 1 1)) (1)) ())
((1 0 1)) (0 1 1)) () (1 0 1)))).
(run (n)
(<o n n))
1)))
120
54
((() ( 0 ! 1 ) () ())
((1)) ( 0 1 ! 2 ) () (1)))
(( 0 1)) ( 0 1)) (1)) ())
((0 0 1)) (1 0 1)) () (0 0 1)))
((0 0 1)) ( 0 1)) (0 1)) ())
(( 0 1)) ( 1 2 3 ! 4 ) () ( 0 1)))
(( 0 1 1)) ( 2 3 4 5 ! 6 ) () ( 0
(( 0 1 1)) ( 0 1 1)) (1)) ())).
55
Yes.
(( 0 1)) ( 0 1)) (1)) ())
represents the two values
((0 1)) (0 1)) (1)) ()) and
((1 1)) (1 1)) (1)) ()).
56
Yes.
1)))
Chapter 8
1)) (
57
Yes.
(( 0 1 1)) ( 0 1 1)) (1)) ())
represents the four values
((0 0 1)) (0 0 1)) (1)) ()),
((1 0 1)) (1 0 1)) (1)) ()),
((0 1 1)) (0 1 1)) (1)) ()), and
((1 1 1)) (1 1 1)) (1)) ()).
58
Yes.
59
Yes.
(() ( 0 ! 1 ) () ())
represents the values
(() (1)) () ())
(() (0 1)) () ())
(() (1 1)) () ())
(() (0 0 1)) () ())
(() (1 0 1)) () ())
(() (0 1 1)) () ())
(() (1 1 1)) () ())
(() (0 0 0 1)) () ())
(() (1 0 0 1)) () ())
(() (0 1 0 1)) () ())
(() (1 1 0 1)) () ())
(() (0 0 1 1)) () ())
(() (1 0 1 1)) () ())
...
60
No,
since it is impossible to write every ground
value that is represented by
(() ( 0 ! 1 ) () ()).
61
No.
) () ()),
Is (() ( 0 !
notation?
121
62
Define o .
63
122
(define o
(lambda (n m q r )
(condi
(( () q) ( n r ) (<o n m))
(( (1)) q) ( () r ) ( n m)
(<o r m))
((<o m n) (<o r m)
(fresh (mq)
(!l o mq n)
(o m q mq)
(+o mq r n)))
(else #u)))).
64
65
66
Yes.
The divisor m is greater than the dividend
n, which means that m cannot be zero.
Also, since m is greater than n and n is
equal to r, we know that m is greater than
the remainder r. By enforcing the second
restriction, we automatically enforce the
first.
Chapter 8
67
68
69
70
71
(),
since it fails.
123
72
(run (m)
(fresh (r )
(o (1 0 1)) m (1 1 1)) r )))
73
(run (m)
(fresh (r )
(o (1 0 1)) m (1 1 1)) r )))
74
(define
(lambda (n m q r )
(fresh (mq)
(<o r m)
(!l o mq n)
(o m q mq)
(+o mq r n))))
o
124
75
Chapter 8
76
Yes,
the new o relies on split o .
(define split o
(lambda (n r l h)
(condi
(( () n) ( () h) ( () l ))
((fresh (b n
)
( (0 b ! n
) n)
( () r )
( (b ! n
) h)
( () l )))
((fresh (
n)
( (1 ! n
) n)
( () r )
( n
h)
( (1)) l )))
((fresh (b n
a r)
( (0 b ! n
) n)
( (a ! r) r )
( () l )
(split o (b ! n
) r () h)))
((fresh (
n a r)
( (1 ! n
) n)
( (a ! r) r )
( (1)) l )
(split o n
r () h)))
((fresh (b n
a r
l)
( (b ! n
) n)
( (a ! r) r )
( (b !
l)) l )
(pos o
l)
(split o n
r
l h)))
(else #u))))
125
77
78
79
126
80
81
It has no value.
We cannot divide an odd number by two
and get a remainder of zero. The old
definition of o never stops looking for
values of y and z that satisfy the division
relation, even though no such values exist.
With the latest definition of o as defined
in frame 76, however, the expression fails
immediately.
Chapter 8
(define
(lambda (n b q r )
(condi
(( (1)) n) (pos o b) ( () q) ( () r ))
(( () q) (<o n b) (+o r (1)) n))
(( (1)) q) (>1o b) (=l o n b) (+o r b n))
(( (1)) b) (pos o q) (+o r (1)) n))
(( () b) (pos o q) ( r n))
(( (0 1)) b)
(fresh (a ad dd)
(pos o dd)
( (a ad ! dd)) n)
(exp2 o n () q)
(fresh (s)
(split o n dd r s))))
((fresh (a ad add ddd)
(conde
(( (1 1)) b))
(else ( (a ad add ! ddd)) b))))
(<l o b n)
(fresh (bw1 bw nw nw1 ql1 ql s)
(exp2 o b () bw1 )
(+o bw1 (1)) bw )
(<l o q n)
(fresh (q1 bwq1 )
(+o q (1)) q1 )
(o bw q1 bwq1 )
(<o nw1 bwq1 ))
(exp2 o n () nw1 )
(+o nw1 (1)) nw )
(o nw bw ql1 s)
(+o ql (1)) ql1 )
(conde
(( q ql ))
(else (<l o ql q)))
(fresh (bql qh s qdh qd)
(repeated-mul o b ql bql)
(o nw bw1 qh s)
(+o ql qdh qh )
(+o ql qd q)
(conde
(( qd qdh))
(else (<o qd qdh)))
(fresh (bqd bq1 bq)
(repeated-mul o b qd bqd)
(o bql bqd bq)
(o b bq bq1 )
(+o bq r n)
(<o n bq1 )))))
(else #u))))
82
(define exp2 o
(lambda (n b q)
(condi
(( (1)) n) ( () q))
((>1o n) ( (1)) q)
(fresh (s)
(split o n b s (1)))))
((fresh (q1 b2 )
(alli
( (0 ! q1 ) q)
(pos o q1 )
(<l o b n)
(append o b (1 ! b)) b2 )
(exp2 o n b2 q1 ))))
((fresh (q1 nh b2 s)
(alli
( (1 ! q1 ) q)
(pos o q1 )
(pos o nh )
(split o n b s nh )
(append o b (1 ! b)) b2 )
(exp2 o nh b2 q1 ))))
(else #u))))
(define repeated-mul o
(lambda (n q nq)
(conde
((pos o n) ( () q) ( (1)) nq))
(( (1)) q) ( n nq))
((>1o q)
(fresh (q1 nq1 )
(+o q1 (1)) q)
(repeated-mul o n q1 nq1 )
(o nq1 n nq)))
(else #u))))
127
83
84
85
86
87
Yes.
The logarithm relation is similar to the
division relation, but with exponentiation
in place of multiplication.
88
89
(run (r )
(log o (0 1 1 1)) (0 1)) (1 1)) r ))
128
(0 1 1)),
since 14 = 23 + 6.
Chapter 8
90
(((1)) ( 0 1 ! 2 ) (1 1 0 0 0 0 1)))
(() ( 0 1 ! 2 ) (0 0 1 0 0 0 1)))
((0 1)) (0 1 1)) (0 0 1)))
((0 0 1)) (1 1)) (0 0 1)))
((1 0 1)) (0 1)) (1 1 0 1 0 1)))
((0 1 1)) (0 1)) (0 0 0 0 0 1)))
((1 1 1)) (0 1)) (1 1 0 0 1)))
((0 0 0 1)) (0 1)) (0 0 1)))),
since
68 = 1n + 67 where n is greater than one,
68 = 0n + 68 where n is greater than one,
68 = 26 + 4,
68 = 43 + 4,
68 = 52 + 43,
68 = 62 + 32,
68 = 72 + 19, and
68 = 82 + 4.
91
Thats easy.
(run (s)
(fresh (b q r )
(log o (0 0 1 0 0 0 1)) b q r )
(>1o q)
( (b q r ) s)))
8
(define expo
(lambda (b q n)
(log o n b q ())))
92
(1 1 0 0 1 1 1 1)),
which is the same as (build-num 243).
THIS IS A NAPKIN!
129
Chapter 9
Thats easy.
131
What is
(z ! a))
b.
(rhs (z ! b)))
What is the value of
The variable w .
(rhs (z ! w ))
What is the value of
10
(rhs (z ! (x e y))))
What is
11
((z ! a)) (x ! w ) (y ! z ))
Is
12
13
((z ! a)) (x ! x ) (y ! z ))
a substitution?
Here is empty-s.
(define empty-s ())
What does it represent?
132
Chapter 9
14
a,
15
a,
17
18
It has no value,
because we never stop walking. The
substitution ((x ! y)) (z ! x ) (y ! z )) is
said to be circular.
16
19
b,
The substitution
((x ! y)) (w ! b)) (z ! x ) (y ! z )) is
circular, but the walk still terminates.
20
21
Yes.
133
22
23
24
(walk x
((y ! b)) (x ! y)) (v ! x ) (w ! x ) (u ! w )))
The value of the expression below is z . What
are the values of the walks of u, v , and w
(walk x
((y ! z ) (x ! y)) (v ! x ) (w ! x ) (u ! w )))
What is the value of
25
The list (x e x ).
134
26
27
Yes.
(cond
((assq v s) f )
(else v ))
Chapter 9
28
29
It has no value,
since the extended substitution is the same
as the one in frame 18.
30
31
e.
32
(define ext-s
(lambda (x v s)
(cons (x ! v ) s)))
What is the value of
(walk x (ext-s x y ((z ! x ) (y ! z ))))
33
b.
34
w.
35
135
Here is unify.
36
(define unify
(lambda (v w s)
(let ((v (walk v s))
(w (walk w s)))
(cond
((eq? v w ) s)
((var? v ) (ext-s v w s))
((var? w ) (ext-s w v s))
((and (pair? v ) (pair? w ))
(cond
((unify (car v ) (car w ) s)
(lambda (s)
(unify (cdr v ) (cdr w ) s)))
(else #f)))
((equal? v w ) s)
(else #f)))))
37
38
39
136
Chapter 9
40
41
42
43
44
(walk x
((y ! (a z c))) (x ! y)) (z ! a))))
45
(a a c)).
The walked value of x is (a z c)). Then the
walk*ed values of each value in the list are
used to create a new list.
(a w c)).
The walked value of x is (z w c)). Then
the walk*ed values of each value in the list
are used to create a new list.
137
46
(walk y
((y ! (w z c))) (v ! b)) (x ! v ) (z ! x )))
Here is walk .
47
(define walk
(lambda (v s)
(let ((v (walk v s)))
(cond
((var? v ) v )
((pair? v )
(cons
(walk (car v ) s)
(walk (cdr v ) s)))
(else v )))))
(w b c)).
The walked value of y is (w z c)). Then
the walk*ed values of each value in the list
are used to create a new list.
(define-syntax project
(syntax-rules ()
(( (x . . . ) g . . . )
(G (s)
(let ((x (walk x s)) . . . )
((all g . . . ) s))))))
where G (see appendix) is just lambda. project is
syntactically like fresh, but it binds diffferent values to the
lexical variables. project binds walk*ed values, whereas
fresh binds variables using var. For example, the value of
(run (q)
( #f q)
(project (q)
( (not (not q)) q)))
Is walk recursive?
is (#f)
); without projecting q, its value would be (), since q,
which is represented using a vector (frame 6), is considered
to be nonfalse when passed as an argument to not.
48
It doesnt.
If v is a fresh variable, then only the first
cond line of walk is ever considered.
Thus walk and walk behave the same if v
is fresh.
49
50
138
Chapter 9
51
52
(define reify-s
(lambda (v s)
(let ((v (walk v s)))
(cond
((var? v )
(ext-s v (reify-name (size-s s)) s))
((pair? v ) (reify-s (cdr v )
(reify-s (car v ) s)))
(else s)))))
Here is reify-name.
(define reify-name
(lambda (n)
(string!symbol
(string-append " " "." (number!string n)))))
The functions string!symbol, string-append, and
number!string are standard; and size-s is length, which is
also standard.
53
).
).
54
55
).
56
(a
c 0 ),
0
since r s fresh variable w is replaced by the
reified name 0 (see frame 45).
139
57
58
(define reify
(lambda (v )
(walk v (reify-s v empty-s))))
What is the value of
(let ((s ((y ! (z w c w )) (x ! y)) (z ! a)))))
(reify (walk x s)))
59
(a
c 0 ),
0
since this is just a restatement of frame 56.
Within run, (reify (walk x s)) transforms
the value associated with x by first
removing all nonfresh variables. This is
done by (walk x s), which returns a value
whose variables are fresh. The call to reify
then transforms the walk*ed value,
replacing each fresh variable with its
reified name.
(define ext-s
(lambda (x v s)
(cond
((occurs x v s) #f)
(else (ext-s x v s)))))
(define occurs
(lambda (x v s)
(let ((v (walk v s)))
(cond
((var? v ) (eq? v x ))
((pair? v )
(or
(occurs x (car v ) s)
(occurs x (cdr v ) s)))
(else #f)))))
(define unify
(lambda (v w s)
(let ((v (walk v s))
(w (walk w s)))
(cond
((eq? v w ) s)
((var? v ) (ext-s v w s))
((var? w ) (ext-s w v s))
((and (pair? v ) (pair? w ))
(cond
((unify (car v ) (car w ) s)
(lambda
(s)
(unify (cdr v ) (cdr w ) s)))
(else #f)))
((equal? v w ) s)
(else #f)))))
140
Chapter 9
60
61
It has no value.
(run1 (x )
( (x ) x ))
62
(run (q)
(fresh (x )
( (x ) x )
( #t q)))
1
63
(run1 (q)
(fresh (x y)
( (x ) y)
( (y)) x )
( #t q)))
(x ) x ))
64
(#t)).
Although the substitution is circular, x is
not reached by the walk of q from within
run.
(#t)).
Although the substitution is circular,
neither x nor y is reached by the walk of q
from within run.
(),
where is the
same as , except that it
relies on unify instead of unify.
Here is .
(define
(lambda (v w )
(G (s)
(cond
((unify v w s) #s)
(else (#u s))))))
where #s and #u are defined in the appendix, and G is just
lambda.
141
65
It has no value.
(run (x )
(fresh (y z )
( x z )
( (a b z ) y)
( x y)))
1
66
().
(run (x )
(fresh (y z )
( x z )
((a b z ) y)
( x y)))
1
x y) fails
67
((y ! (a b z )) (z ! x )).
y) fails because
( x
(occurs x y ((y
! (a b z )) (z ! x )))
returns #t. occurs first finds
ys
association, (a b z ). occurs then searches
(a b z ) and at each step makes sure that
the rhs is walked if it is a variable. When z
is walked, walk returns the fresh variable
x , which means that we have an occurrence
of x in y.
68
69
have no value?
142
Chapter 9
70
(run (x )
( (x ) x ))
1
PALM TREES!
143
Chapter 10
Thin Ice
Does
No,
because the question of the first conda
line is the goal #u, so conda tries the
second line.
Yes,
because the question of the first conda
line is the goal #u, so conda tries the
second line.
No,
because the question of the first conda
line is the goal #s, so conda tries the
answer of the first line.
Yes,
because the question of the first conda
line is the goal #s, so conda tries the
answer of the first line.
(cond
(#u #s)
(else #u))
a
succeed?
Does
(cond
(#u #s)
(else #s))
a
succeed?
Does
(cond
(#s #u)
(else #s))
a
succeed?
Does
(conda
(#s #s)
(else #u))
succeed?
(olive)),
because ( olive x ) succeeds; therefore, the
answer of the first conda line is #s. The #s
preserves the association of x to olive.
Thin Ice
145
(run (x )
(conda
(( olive x ) #s)
(( oil x ) #s)
(else #u)))
(run (x )
(conda
(( virgin x ) #u)
(( olive x ) #s)
(( oil x ) #s)
(else #u)))
What is the value of
(run (q)
(fresh (x y)
( split x )
( pea y)
(conda
(( split x ) ( x y))
(else #s)))
( #t q))
146
().
( split x ) succeeds, since x is already
associated with split. ( x y) fails,
however, since x and y are associated with
different values.
#t.
( x y) fails, since x and y are associated
with different values. The question of the
first conda line fails, therefore we try the
second conda line, which succeeds.
Chapter 10
10
11
(define not-pasta o
(lambda (x )
(conda
(( pasta x ) #u)
(else #s))))
(spaghetti)),
because x starts out fresh, but the
question (not-pasta o x ) associates x with
pasta, but then fails. Since (not-pasta o x )
fails, we try ( spaghetti x ).
12
(),
because (not-pasta o x ) succeeds, which
shows the risks involved when using
conda . We cant allow a fresh variable to
become nonfresh as part of a conda
question.
Thin Ice
147
13
(run (q)
(conda
(always o #s)
(else #u))
( #t q))
14
(run (q)
(condu
(always o #s)
(else #u))
( #t q))
It has no value,
since run never finishes building the list
of #ts.
(#t)),
because condu is like conda , except that
the successful question, here always o ,
succeeds only once.
15
It has no value,
since run never finishes building the list
of #ts.
16
(run (q)
(condu
(#s always o )
(else #u))
( #t q))
148
Chapter 10
17
18
(),
because condu s successful question
succeeds only once.
Here is once o .
(define once o
(lambda (g)
(condu
(g #s)
(else #u))))
19
(tea)).
The first conde line of teacup o succeeds.
Since once o s goal can succeed only once,
there are no more values. But, this breaks
The Third Commandment.
Thin Ice
149
20
(run (q)
(once o (sal o never o ))
#u)
1
21
().
The first conde line of sal o succeeds. This
is followed by #u, which fails. Since once o s
goal can succeed only once, this avoids
never o , so the run fails. This use of once o
obeys The Third Commandment.
(run (r )
(conde
((teacup o r ) #s)
(( #f r ) #s)
(else #u)))
22
(run (r )
(conda
((teacup o r ) #s)
(( #f r ) #s)
(else #u)))
23
(run (r )
( #f r )
(conda
((teacup o r ) #s)
(( #f r ) #s)
(else #u)))
150
24
(tea cup)),
breaking The Third Commandment.
(#f)),
since this value is included in frame 21.
(#f)).
conda and condu often lead to fewer
values than a similar expression that uses
conde . Knowing that helps determine
whether to use conda or condu , or the
more general conde or condi .
Chapter 10
25
Here is bump o .
26
(define bump o
(lambda (n x )
(conde
(( n x ) #s)
(else
(fresh (m)
(o n (1)) m)
(bump o m x ))))))
Okay.
((1 1 1))
(0 1 1))
(1 0 1))
(0 0 1))
(1 1))
(0 1))
(1))
()).
Here is gen&test o .
27
(define gen&test o
(lambda (op i j k )
(once o
(fresh (x y z )
(op x y z )
( i x )
( j y)
( k z )))))
#t ,
because four plus three is seven, but there
is more.
Thin Ice
28
0
, (), and
, respectively.
151
29
30
31
32
33
34
35
36
152
( i x ) succeeds,
since i is associated with (0 0 1)) and x is
fresh. As a result, x is associated with
(0 0 1)).
( j y) fails,
since j is associated with (1 1)) and y is
associated with ().
( i x ) fails,
since i is still associated with (0 0 1)) and x
is associated with ().
( i x ) fails,
since i is still associated with (0 0 1)) and x
is associated with (1)).
( i x ) succeeds,
associating x , and therefore z , with
(0 0 1)).
Chapter 10
37
38
( j y) succeeds,
since both j and y are associated with
(1 1)).
( k z ) succeeds,
since both k and z are associated with
(0 0 1)).
39
40
It has no value.
41
Never.
(run (q)
(gen&test o +o (0 0 1)) (1 1)) (0 1 1))))
1
Why doesnt
(run1 (q)
(gen&test o +o (0 0 1)) (1 1)) (0 1 1))))
have a value?
Thin Ice
42
153
Here is enumerate o .
43
(define enumerate o
(lambda (op r n)
(fresh (i j k )
(bump o n i )
(bump o n j )
(op i j k )
(gen&test o op i j k )
( (i j k ) r ))))
What is the value of
(run (s)
(enumerate o +o s (1 1))))
44
45
46
It seems so.
47
Thats confusing.
154
Chapter 10
48
49
At least once?
50
Yes,
since we are interested in only one value.
We first determine (op x y z ), where x , y,
and z are fresh. Then we see if that result
matches ((0 1)) (1 1)) (1 0 1))). If not, we
try (op x y z ) again, and again.
51
52
53
Thin Ice
155
54
(run (s)
(enumerate o +o s (1 1))))
55
56
(run (s)
(enumerate o +o s (1 1 1))))
1
57
(define gen-adder o
(lambda (d n m r )
(fresh (a b c e x y z )
( (a ! x ) n)
( (b ! y)) m) (pos o y)
( (c ! z ) r ) (pos o z )
(all
(full-adder o d a b c e)
(adder o e x y z )))))
58
It has no value.
(run1 (q)
(gen&test o +o (0 1)) (1 1)) (1 0 1))))
using the second definition of gen-adder o
156
Chapter 10
59
Why doesnt
(run1 (q)
(gen&test o +o (0 1)) (1 1)) (1 0 1))))
have a value?
60
61
62
63
Yes, of course.
))
(run (q)
(enumerate o +o q (1 1 1))))
Thin Ice
157
Appendix A
159
(define-syntax run
9 : 6, 13, 47, 58
(syntax-rules ()
(( n
(x ) g . . . )
(let ((n n
) (x (var x)))
(if (or (not n) (> n 0))
(map n
(lambda (s)
(reify (walk x s)))
((all g . . . ) empty-s))
())))))
(define-syntax mzero
(syntax-rules ()
(( ) #f)))
(define-syntax unit
(syntax-rules ()
(( a) a)))
(define-syntax choice
(syntax-rules ()
(( a f ) (cons a f ))))
(define-syntax case
(syntax-rules ()
(( e on-zero ((
a) on-one) ((a f ) on-choice))
((not a ) on-zero)
((not (and
(pair? a )
(let ((
a a ))
on-one))
(define map
(lambda (n p a )
(case a
()
((a)
(cons (p a) ()))
((a f )
(cons (p a)
(cond
(define-syntax all
(syntax-rules ()
(( g . . . ) (all-aux bind g . . . ))))
160
9 : 27, 36
(define-syntax alli
(syntax-rules ()
(( g . . . ) (all-aux bind i g . . . ))))
(define-syntax condi
(syntax-rules ()
(( c . . . ) (cond-aux if i c . . . ))))
9:6
(define-syntax conda
(syntax-rules ()
(( c . . . ) (cond-aux if a c . . . ))))
(define-syntax condu
(syntax-rules ()
(( c . . . ) (cond-aux if u c . . . ))))
Appendix A
(define mplus
(lambda (a f )
(case a
(f )
((a) (choice a f ))
((a f0 ) (choice a
(F () (mplus (f0 ) f )))))))
(define mplusi
(lambda (a f )
(case a
(f )
((a) (choice a f ))
((a f0 ) (choice a
(F () (mplusi (f ) f0 )))))))
(define bind
(lambda (a g)
(case a
(mzero)
((a) (g a))
((a f ) (mplus (g a)
(F () (bind (f ) g)))))))
(define bind i
(lambda (a g)
(case a
(mzero)
((a) (g a))
((a f ) (mplusi (g a)
(F () (bind i (f ) g)))))))
(define-syntax cond-aux
(syntax-rules (else)
(( ifer ) #u)
(( ifer (else g . . . )) (all g . . . ))
(( ifer (g . . . )) (all g . . . ))
(( ifer (g0 g . . . ) c . . . )
(ifer g0
(all g . . . )
(cond-aux ifer c . . . )))))
(define-syntax all-aux
(syntax-rules ()
(( bnd) #s)
(( bnd g) g)
(( bnd g0 g . . . )
(let ((
g g0 ))
(G (s)
(bnd (
g s)
(G (s) ((all-aux bnd g . . . ) s))))))))
if e
(define-syntax if i
(syntax-rules ()
(( g0 g1 g2 )
(G (s)
(mplusi ((all g0 g1 ) s) (F () (g2 s)))))))
(define-syntax
(syntax-rules ()
(( g0 g1 g2 )
(G (s)
(mplus ((all g0 g1 ) s) (F () (g2 s)))))))
(define-syntax if a
(syntax-rules ()
(( g0 g1 g2 )
(G (s)
(define-syntax if u
(syntax-rules ()
(( g0 g1 g2 )
(G (s)
161
Appendix B
163
Index
Italic page numbers refer to definitions.
birthdate, 136
bit operators
bit-and o , 88
bit-nand o , 87
bit-not o , 88
bit-xor o , 87
full-adder o , 89
half-adder o , 89
bit-and o , 88
bit-nand o , 87
bit-not o , 88
bit-xor o , 87
Boole, George, 4
Boolean value, 4
bound-o (bound-*o), 113
hypothetical definition, 113
build-num, 93
shows non-overlapping property, 93
bump o , 151
car, 17
car o , 17, 18
Carroll, Lewis, 163
carry bit, 104
case (case-inf), 159, 160
cdr, 19
cdr o , 19
choice, 159, 160
Clocksin, William F., 11, 61, 131, 145
Commandments
The First Commandment, 28
The Second Commandment, 48
The Third Commandment, 147
committed-choice, 148
cond macro, ix
(=>), 134
conda (conda), 145, 159, 160
conda -line answer, 145
conda -line question, 145
conde (conde), ix, 11, 159, 160
conde -line answer, 11
conde -line question, 11
condi (condi), 80, 159, 160
condu (condu), 148, 159, 160
cond-aux, 161
conjunction, 159. See also all
fair, 159 (see also alli )
166
cons o , 20, 21
continuation-passing style (CPS), 19
Conway, Thomas, 148
co-refer, 9
cut operator, 148
Dijkstra, Edsger W., 93
discrete logarithm. See log o
disjunction, 159. See also conde
fair, 159 (see also condi )
Dybvig, R. Kent, 131
empty-s, 132
enumerate o , 154
eq-car?, 36
eq-car o , 36
eq?, 22, 136, 140
used to distinguish between variables, 136
eq o , 23
exp2 o (help function for log o ), 127
expo , 129
ext-s,135
ext-s (ext-s-check), 140
fail (#u), ix, 3, 159, 160
fair conjuction, 159. See also alli
fair disjunction, 159. See also condi
Felleisen, Matthias, 131
Findler, Robert Bruce, 131
The First Commandment, 28
first-value, 44
Flatt, Matthew, 131
flatten, 71
flatten o , 71
flattenrev o , 74
food, x
fresh, ix, 6, 160
fresh variable, 6
full-adder o , 89
functional programming, ix
functions (as values), ix, 3
Gardner, Martin, 163
gen&test o , 151
gen-adder o , 104
using all instead of alli , 156
goal, 3, 159
Index
memo , 48
simplified definition, 50
member?, 36
member o , 36
memberrev o , 44
Mercury, 148
soft-cut operator, 148
Moggi, Eugenio, 159
monadic operation, 159
mplus, 159, 161
mplusi (mplusi), 159, 161
mzero, 159, 160
n-representative, 99
Nagel, Ernest, 163
Naish, Lee, 148
never o , 77
Newman, James R., 163
non-overlapping property, 93
notational conventions, ix
not-pasta o , 147
no value (for an expression), 29
null?, 21
null o , 22
number!string, 139
Index
unwrap, 68
unwrap o , 69
with swapped conde lines, 70
Vaillancourt, Dale, 159
value of a run/run expression, 5
var, 131, 136
var?, 131, 136
variable
anonymous, 131
fresh, 6
lexical, 138
reified, 8
vector, 131
vector (cannot pass to unify), 136
vector?, 131
Voronkov, Andrei, 132
Wadler, Philip L., 159
walk, 133, 134
walk (walk*), 138
Wand, Mitchell, 159
width (of a number), 102
169