Expressions to avoid (if <p> #t #f) ; worst (append (list1 <x>) <ys>) ; most common (cons <x> (cons <y> ’())) ; prefer ‘list2‘
Homework alert Functions list-of?, formula? • Can be passed any value • Must handle all cases (Figure 2.2, page 94)
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
Reflection: Solving Boolean formulas On your homework, you will use continuations to organize 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])
(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))))
; !(x /\ y /\ z)
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])
Solving Boolean Formulae (val f1 (make-and (list4 ’x ’y ’z (make-not ’x)))) ; x /\ y /\ z /\ !x Answer: NONE
Solving Boolean Formulae (val f2 (make-not (make-or (list2 ’x ’y)))) ; !(x \/ y) Answer: { x | - > #f, y | - > #f }
Solving Boolean Formulae (val f3 (make-or (list2 ’x ’y))) ; x \/ y Answer: Two solutions! { x |-> #t, ... } { y |-> #t, ... }
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, ... }, ...
Finding a satisfying assignment Example formula: (x \/ y) /\ (!x /\ !z)
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.
Compose a network of solvers using continuations start +-----------+ success --------->| |------------> | solver | <---------| |<----------- fail +-----------+ resume start Passed current (partial solution), fail , success (On homework, “solution” is assignment) Call with no params if current won’t work fail Call with extended solution + resume success Called by downstream solver with no params if resume extended solution won’t work A composable unit!
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)))
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
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
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
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
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
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. ]
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!
Lisp and Scheme Retrospective
Five powerful questions 1. What are the values? 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?
� 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
Next steps Before tomorrow’s lecture, Consider good and bad points of Scheme (Informed by your experience)
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)
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])
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
Recommend
More recommend