looking back
play

Looking back Write one thing you learned about higher-order and - PowerPoint PPT Presentation

Looking back Write one thing you learned about higher-order and anonymous functions. Your answers may be anonymously shared with your classmates. Reflection Consider the following algebraic laws for list reversal: reverse () = ()


  1. Looking back Write one thing you learned about higher-order and anonymous functions. Your answers may be anonymously shared with your classmates.

  2. Reflection Consider the following algebraic laws for list reversal: reverse ’() = ’() reverse (x .. xs) = reverse xs .. reverse ’(x) = reverse xs .. ’(x) where .. denotes the append operation on lists. Now consder the corresponding code: (define reverse (xs) (if (null? xs) ’()

  3. (append (reverse (cdr xs)) (list1 (car xs))))) where list1 is a function that makes a one-element list from its argument. Answer these questions: • For a list reversal function to be considered to have good performance, what should its running time be in terms of the length of its argument? • What is the running time of the reverse function above?

  4. Naive list reversal (define reverse (xs) (if (null? xs) ’() (append (reverse (cdr xs)) (list1 (car xs)))))

  5. Tail calls Intuition: In a function, a call is in tail position if it is the last thing the function does. (define reverse (xs) (if (null? xs) ’() (append (reverse (cdr xs)) (list1 (car xs)))))

  6. Tail calls Intuition: In a function, a call is in tail position if it is the last thing the function does. (define reverse (xs) (if (null? xs) ’() (append (reverse (cdr xs)) (list1 (car xs))))) A tail call is a call in tail position.

  7. What is tail position? Tail position is defined inductively: • The body of a function is in tail position • When (if e1 e2 e3) is in tail position, so are e2 and e3 • When (let (...) e) is in tail position, so is e , and similary for letrec and let* . • When (begin e1 ... en) is in tail position, so is en . Idea: The last thing that happens

  8. Check your understanding: Tail Position Consider the following code -> (define foldr (plus zero xs) (if (null? xs) zero (plus (car xs) (foldr plus zero (cdr xs))))) Now answer the following questions. The occurrence of expression zero in the true-branch of the if expression is in tail position. • True • False Answer: True. The body of the function is in tail

  9. position, which makes the if expression itself in tail position. The rule for if is that the true and false branches share the tail status of the if expression, so zero is in tail position. The occurrence of expression plus in the false-branch of the if expression is in tail position. • True • False Answer: True. The body of the function is in tail position, which makes the if expression itself in tail position. The rule for if is that the true and false branches share the tail status of the if expression. The call to plus is the last thing in the

  10. false-branch, so it is in tail position. The occurrence of expression foldr in the false-branch of the if expression is in tail position. • True • False Answer: False. The call to foldr is within the call to plus in the false-branch of the if expression, so it cannot be the last thing that happens.

  11. Tail-call optimization & accumulating parameters Tail-call optimization • Anything in tail position is the last thing executed, so its stack frame can be recycled • Before executing a call in tail position, abandon current stack frame • Results in asymptotic space savings Accumulating Parameter • Add a parameter to accumulate answer • Moves recursive call to tail position

  12. Example: Accumulating reverse function Key ideas: • Recursive call is in a tail position • Accumulating parameter collects answer Contract: (revapp xs ys) = (append (reverse xs) ys) Laws: (revapp ’() ys) == ys (revapp (cons z zs) ys) == (revapp zs (cons z ys))

  13. Reversal by accumulating parameters ; laws: (revapp ’() ys) = ys ; (revapp (cons z zs) ys) = ; (revapp zs (cons z ys)) (define revapp (xs ys) ; return (append (reverse xs) ys) (if (null? xs) ys (revapp (cdr xs) (cons (car xs) ys)))) (define reverse (xs) (revapp xs ’()))

  14. Tail position in revapp (define revapp (xs zs) (if (null? xs) zs (revapp (cdr xs) (cons (car xs) zs))))

  15. Tail position in revapp (define revapp (xs zs) (if (null? xs) zs (revapp (cdr xs) (cons (car xs) zs)))) Values xs and zs go in machine registers. Code compiles to a loop.

  16. Check your understanding: Accumulating Parameters An accumulating parameter to a recursive function f accumulates the answer so that a recursive call to f can be in tail position. • True • False Answer: True. The stack frame of a function call that is not in tail position cannot be shared with subsequent calls because its values may still be needed. • True

  17. • False Answer: True. Tail-call optimizations and the use of accumulating parameters can only result in constant-time improvements to the complexity of a function. • True • False Answer: False. The revapp version of the reverse function is linear in the length of the list being reversed while the naive version of reverse is quadratic.

  18. Reflection Are tail calls familiar? What other programming construct 1. Transfers control to another point in the code? 2. Uses no stack space?

  19. Tail calls as gotos with arguments Goto s • Transfer control to another point in the code • Use no stack space • Can only go to code marked with labels Tail calls • Transfer control to another point in the code • Use no stack space • Can transfer control to any function • Can take parameters!

  20. Continuations: First-class tail calls A continuation is code that represents “the rest of the computation.” • Not a normal function call because continuations never return • Think “goto with arguments” Context: an advanced technique, heavily used in event-driven programming: • GUIs, games, web, embedded devices

  21. Different coding styles Direct style • Last action of a function is to return a value. (This style is what you are used to.) Continuation-passing style (CPS) • Last action of a function is to “throw” answer to a continuation. (For us, tail call to a parameter.)

  22. Uses of continuations • Compiler representation: – Compilers for functional languages often convert direct-style user code to CPS because CPS matches control-flow of assembly. • First-class continuations. – Some languages provide a construct for capturing the current continuation and giving it a name k . – Control can be resumed at captured continuation by throwing to k . • A style of coding that can mimic exceptions • Callbacks in GUI frameworks and web services • Event loops in game programming and other concurrent settings

  23. Implementation • We’re going to simulate continuations with function calls in tail position. • First-class continuations require compiler support. – primitive function that materializes “current continuation” into a variable.

  24. Check your understanding: Continuation Introduction A continuation is different from a normal function because it never returns to the context from which it was invoked. • True • False Answer: True. Continuations cannot take arguments. • True • False Answer:False.

  25. Continuations are used in GUI frameworks and to mimic exceptions. • True • False Answer: True.

  26. Reflection Consider the following algebraic laws for a witness function: (witness p? xs) == x, where (member x xs), provided (exists? p? xs) Now answer this questions: • What should the function do if there exists no such x ?

  27. Design Problem: Missing Value Provide a witness to existence: (witness p? xs) == x, where (member x xs), provided (exists? p? xs) Problem: What if there exists no such x ? Bad ideas: • nil • special symbol fail • run-time error Good idea: exception (but not available in uScheme)

  28. Solution: A New Interface Success and failure continuations! Contract written using properties (not algorithmic) (witness-cps p? xs succ fail) = (succ x) ; where x is in xs and (p? x) (witness-cps p? xs succ fail) = (fail) ; where (not (exists? p? xs))

  29. From contract to laws (witness-cps p? xs succ fail) = (succ x) ; where x is in xs and (p? x) (witness-cps p? xs succ fail) = (fail) ; where (not (exists? p? xs)) Where do we have forms of data? (witness-cps p? ’() succ fail) = ? (witness-cps p? (cons z zs) succ fail) = ? ; when (p? z) (witness-cps p? (cons z zs) succ fail) = ? ; when (not (p? z))

  30. Coding witness with continuations (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)))))

  31. “Continuation-Passing Style” by laws The right-hand side of every law calls a parameter (witness-cps p? xs succ fail) = (succ x) ; where x is in xs and (p? x) (witness-cps p? xs succ fail) = (fail) ; where (not (exists? p? xs))

  32. “Continuation-Passing Style” by code 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

  33. Example Use: Instructor Lookup -> (val 2020f ’((Fisher 105)(Monroe 40)(Chow 116))) -> (instructor-info ’Fisher 2020f) (Fisher teaches 105) -> (instructor-info ’Chow 2020f) (Chow teaches 116) -> (instructor-info ’Votipka 2020f) (Votipka is-not-on-the-list)

Recommend


More recommend