SLIDE 1
Expressions to avoid
(if <p> #t #f) ; worst (append (list1 <x>) <ys>) ; most common (cons <x> (cons <y> ’())) ; prefer ‘list2‘
SLIDE 2 Homework alert
Functions list-of?, formula?
- Can be passed any value
- Must handle all cases (Figure 2.2, page 94)
SLIDE 3
Review: “Continuation-Passing Style”
All tail positions are continuations or recursive calls
(define witness-cps (p? xs succ fail) (if (null? xs) (fail) (let ([z (car xs)]) (if (p? z) (succ z) (witness-cps p? (cdr xs) succ fail)))))
Compiles to tight code
SLIDE 4 Reflection: Solving Boolean formulas
On your homework, you will use continuations to
- rganize a search to find satisfying assignments for
Boolean formulae. A formula has one of these forms:
- Symbol (stands for a variable)
- Record (make-not f); f is a formula
- Record (make-or
fs); fs is a list of formulas
- Record (make-and fs); fs is a list of formulas
given the following record declarations: (record not [arg]) (record or [args])
SLIDE 5
(record and [args]) For each formula, find a satisfying assignment or explain why none exists. (val f1 (make-and (list4 ’x ’y ’z (make-not ’x)))) ; x /\ y /\ z /\ !x (val f2 (make-not (make-or (list2 ’x ’y)))) ; !(x \/ y) (val f3 (make-or (list2 ’x ’y))) ; x \/ y (val f4 (make-not (make-and (list3 ’x ’y ’z))))
SLIDE 6
; !(x /\ y /\ z)
SLIDE 7 Using continuations to solv Boolean formulas
A formula is one of these:
- Symbol (stands for a variable)
- Record (make-not f); f is a formula
- Record (make-or fs); fs is a list of formulas
- Record (make-and fs); fs is a list of formulas
given the following record definitions. (record not [arg]) (record or [args]) (record and [args])
SLIDE 8
Solving Boolean Formulae
(val f1 (make-and (list4 ’x ’y ’z (make-not ’x)))) ; x /\ y /\ z /\ !x Answer: NONE
SLIDE 9
Solving Boolean Formulae
(val f2 (make-not (make-or (list2 ’x ’y)))) ; !(x \/ y) Answer: { x |-> #f, y |-> #f }
SLIDE 10
Solving Boolean Formulae
(val f3 (make-or (list2 ’x ’y))) ; x \/ y Answer: Two solutions! { x |-> #t, ... } { y |-> #t, ... }
SLIDE 11
Solving Boolean Formulae
(val f4 (make-not (make-and (list3 ’x ’y ’z)))) ; !(x /\ y /\ z) Answer: Many solutions (all 7 ways the variables can not all be #t): { x |-> #f, ... }, ...
SLIDE 12
Finding a satisfying assignment
Example formula: (x \/ y) /\ (!x /\ !z)
SLIDE 13
Problem Decomposition
Goal True False x Check current, maybe extend
: A
Make A False Make A True A
^ B
Both Either A
_ B
Either Both current is partial assignment of truth values to variables.
SLIDE 14 Compose a network of solvers using continuations
start +-----------+ success
|------------> | solver | <---------| |<----------- fail +-----------+ resume
start Passed current (partial solution), fail, success (On homework, “solution” is assignment) fail Call with no params if current won’t work success Call with extended solution + resume resume Called by downstream solver with no params if extended solution won’t work A composable unit!
SLIDE 15
Solving a literal
; (satisfy-literal-true x current succ fail) = ; (succ current fail), when x is bound to #t in cur ; (fail), when x is bound to #f in cur ; (succ (bind x #t current) fail), x unbound in cur (define satisfy-literal-true (x current succ fail) (if (bound? x current) (if (find x current) (succ current fail) (fail)) (succ (bind x #t current) fail)))
SLIDE 16 Check your understanding: Solving a Negated Literal
Consider the schema we’ve been using to find satisfying assignments for Boolean formulas. In the previous video, we walked through how to instantiate the schema for a positive literal. The following questions ask you to do the same thing for a negated literal, which is a term of the form not x where x is a literal.
start +-----------+ success
|------------> | solver | <---------| |<----------- fail +-----------+ resume
SLIDE 17 The start continuation is called with argument current, the partial truth assignment constructed so far. The box needs to describe how to extend current to make the negated variable not x true. If current(x) = #t, what should the box do?
- Call success continuation with current as
argument.
- Call fail continuation
- Call success continuation with current
extended with {x->#t}
- Call success continuation with current
extended with {x->#f} [Answer: If current already has a binding of #t for
SLIDE 18 x, there is no way to extend the environment to also make x false (and hence not x true), so we should call the fail continuation.] If current(x) = #f, what should the box do?
- Call success continuation with current as
argument.
- Call fail continuation
- Call success continuation with current
extended with {x->#t}
- Call success continuation with current
extended with {x->#f} [Answer: If current already has a binding of #f for x, the environment already makes not x true, so we
SLIDE 19 should call the success continuation passing the current environment. There’s no need to change it because it already has the binding we need for x.] If x is not in current, what should the box do?
- Call success continuation with current as
argument.
- Call fail continuation
- Call success continuation with current
extended with {x->#t}
- Call success continuation with current
extended with {x->#f} [Answer: We can make not x true by extending current with a binding that maps x to #f, so we
SLIDE 20 call the success continuation with this extended environment.] The success continuation takes two arguments: current (the partial solution found so far) and resume (the continuation that takes over if current is found to be inconsistent with some new part of the formula. When calling the success continuation, what should we pass as the resume continuation?
- (lambda (x) x)
- fail
- (lambda (x) (not x))
- start
SLIDE 21
Please explain your answer. [Answer: The only way to make not x true is to make the variable x false. If a downstream part of the search determines that x cannot be false, then there is nothing further we can do, so if we are asked to resume, we need to indicate failure. We communicate that information by passing fail as the resume continuation argument when we call the success continuation. ]
SLIDE 22
Continuations for the solver
A big box contains two smaller boxes A and B There are two ways to wire them up (board) Imagine A and B as formulas Imagine A as a formula, B as a list of formulas!
SLIDE 23
Lisp and Scheme Retrospective
SLIDE 24 Five powerful questions
What do expressions/terms evaluate to?
- 2. What environments are there?
What can names stand for?
- 3. What is the abstract syntax?
Syntactic categories? Terms in each category?
- 4. How are terms evaluated?
Judgments? Evaluation rules?
- 5. What’s in the initial basis?
Primitives and predefined, what is built in?
SLIDE 25 Scheme and the Five Questions
Values: S-expressions (esp. cons cells and closures) Environments: A name stands for a mutable location holding a value Abstract syntax: Expressions and definitions, imperative core, let, lambda Evaluation rules: lambda captures environment Initial basis: powerful higher-order functions
SLIDE 26
Next steps
Before tomorrow’s lecture, Consider good and bad points of Scheme (Informed by your experience)
SLIDE 27 Full Scheme: Macros
A Scheme program is just another S-expression
- Function define-syntax manipulates syntax at
compile time
- Macros are hygienic—name clashes impossible
- let, &&, record, others implemented as macros
(See book sections 2.16, 2.17.4)
SLIDE 28
Full Scheme: Conditionals
(cond [c1 e1] ; if c1 then e1 [c2 e2] ; else if c2 then e2 ... ... [cn en]) ; else if cn then en ; Syntactic sugar---’if’ is a macro: (if e1 e2 e3) == (cond [e1 e2] [#t e3])
SLIDE 29 Full Scheme: Mutation
Not only variables can be mutated. Mutate heap-allocated cons cell: (set-car! ’(a b c) ’d) => (d b c) Circular lists, sharing, avoids allocation
- still for specialists only