A apresentação está carregando. Por favor, espere

A apresentação está carregando. Por favor, espere

Continuations Programação Funcional Avançada Vítor De Araújo

Apresentações semelhantes


Apresentação em tema: "Continuations Programação Funcional Avançada Vítor De Araújo"— Transcrição da apresentação:

1 Continuations Programação Funcional Avançada Vítor De Araújo
Tópicos Especiais em Computação V – INF05504 Programação Funcional Avançada Continuations Vítor De Araújo

2 Continuations function foo(n) { return n*n; } ▶ 1 + foo(3) 10

3 Continuations function foo(n) { return(n*n); } ▶ 1 + foo(3) 10

4 Continuations function foo(n) { return(n*n); } ▶ 1 + foo(3) 10
return(x) = 1 + x return = λx. 1 + x

5 Continuations function foo(n) { let r = return; return(n*n); }
10 return(x) = 1 + x return = λx. 1 + x

6 Continuations function product(list) { return foldl((λx,y -> x*y),
1, list); } ▶ print product([2,3,0,1,4,5,6,7,8,9,23,42,71]);

7 Continuations function product(list) { let out = return;
return foldl((λx,y -> x*y), 1, list); } ▶ print product([2,3,0,1,4,5,6,7,8,9,23,42,71]);

8 Continuations function product(list) { let out = return;
return foldl((λx,y -> if (y==0) out(0) else x*y), 1, list); } ▶ print product([2,3,0,1,4,5,6,7,8,9,23,42,71]);

9 Continuations function foo(n) { let r = return; return(n*n); }
10

10 Continuations let c; function foo(n) { let r = return; return(n*n); }
10

11 Continuations let c; function foo(n) { c = return; return(n*n); }
10

12 call-with-current-continuation
(call-with-current-continuation f) a.k.a. (call/cc f) Captura a continuation que está esperando o resultado da chamada a call/cc Chama f usando a continuation como argumento function callcc(f) { return f(return); } ▶ 1 + callcc(λcont -> ...)

13 call-with-current-continuation
(call-with-current-continuation f) a.k.a. (call/cc f) Captura a continuation que está esperando o resultado da chamada a call/cc Chama f usando a continuation como argumento function callcc(f) { return f(return); } let c; ▶ 1 + callcc(λcont -> c = cont; 3*3) 10 ▶ c(5) 6

14 call-with-current-continuation
JavaScript impostor ▶ let c; ▶ 1 + callcc(λcont -> c = cont; 3*3) 10 ▶ c(5) 6 Scheme ▶ (define c #f) ▶ (+ 1 (call/cc (lambda (cont) (set! c cont) (* 3 3)))) 10 ▶ (c 5) 6

15 Escapes JavaScript impostor Scheme function product(list) {
let out = return; return foldl((λx,y -> if (y==0) out(0) else x*y), 1, list); } Scheme (define (product list) (call-with-current-continuation (lambda (out) (foldl (lambda (x y) (if (= y 0) (out 0) (* x y))) list))))

16 Generators Python def fibs(): greater = 1 lesser = 0 while True:
print greater greater, lesser = greater+lesser, greater

17 Generators Python Scheme (actually Racket due to printf) def fibs():
greater = 1 lesser = 0 while True: print greater greater, lesser = greater+lesser, greater Scheme (actually Racket due to printf) (define (fibs) (let loop ((greater 1) (lesser 0)) (printf "~a\n" greater) (loop (+ greater lesser) greater)))

18 Generators Python def fibs(): greater = 1 lesser = 0 while True:
yield greater greater, lesser = greater+lesser, greater ▶ f = fibs() ▶ f <generator object fibs at 0xb74c570c> ▶ f.next() 1 2

19 Generators No corpo do gerador, yield
fibs() retorna um gerador f.next() passa o controle para o corpo do gerador No corpo do gerador, yield salva o estado de execução do gerador passa o controle de volta para o chamador de f.next() Na próxima chamada a f.next(), execução é retomada de onde o yield parou Duas continuations envolvidas A continuation do chamador de f.next() A continuation que permite retomar a execução a partir do yield Sure we can implement it

20 Do-It-Yourself generators
(define (fibs) (let ((yield-continuation #f)) (lambda () ...)

21 Do-It-Yourself generators
(define (fibs) (let ((yield-continuation #f)) (lambda () (call-with-current-continuation (lambda (caller-continuation) ... )))))

22 Do-It-Yourself generators
(define (fibs) (let ((yield-continuation #f)) (lambda () (call-with-current-continuation (lambda (caller-continuation) (cond [yield-continuation (yield-continuation #t)] [else <corpo do gerador>] ))))))

23 Do-It-Yourself generators
(define (fibs) (let ((yield-continuation #f)) (lambda () (call-with-current-continuation (lambda (caller-continuation) (cond [yield-continuation (yield-continuation #t)] [else (let loop ((greater 1) (lesser 0)) (yield greater) (loop (+ greater lesser) greater))] ))))))

24 Do-It-Yourself generators
(define (fibs) (let ((yield-continuation #f)) (lambda () (call-with-current-continuation (lambda (caller-continuation) (cond [yield-continuation (yield-continuation #t)] [else (let loop ((greater 1) (lesser 0)) (yield greater) (loop (+ greater lesser) greater))] ))))))

25 Do-It-Yourself generators
(define (fibs) (let ((yield-continuation #f)) (lambda () (call-with-current-continuation (lambda (caller-continuation) (cond [yield-continuation (yield-continuation #t)] [else (let ((yield (lambda (value) (lambda (yc) (set! yield-continuation yc) (caller-continuation value)))))) (let loop ((greater 1) (lesser 0)) (yield greater) (loop (+ greater lesser) greater)))] ))))))

26 Do-It-Yourself generators
▶ (define f (fibs)) ▶ f <procedure> ▶ (f) 1 2 3 5

27 Let's macroize it (define (fibs) (let ((yield-continuation #f))
(lambda () (call-with-current-continuation (lambda (caller-continuation) (cond [yield-continuation (yield-continuation #t)] [else (let ((yield (lambda (value) (lambda (yc) (set! yield-continuation yc) (caller-continuation value)))))) (let loop ((greater 1) (lesser 0)) (yield greater) (loop (+ greater lesser) greater)))] ))))))

28 Let's macroize it (define-syntax generator (syntax-rules ()
((generator body ...) (let ((yield-continuation #f)) (lambda () (call-with-current-continuation (lambda (caller-continuation) (cond [yield-continuation (yield-continuation #t)] [else (let ((yield (lambda (value) (lambda (yc) (set! yield-continuation yc) (caller-continuation value)))))) (let loop ((greater 1) (lesser 0)) (yield greater) (loop (+ greater lesser) greater)))] ))))))))

29 Let's macroize it (define-syntax generator (syntax-rules ()
((generator body ...) (let ((yield-continuation #f)) (lambda () (call-with-current-continuation (lambda (caller-continuation) (cond [yield-continuation (yield-continuation #t)] [else (let ((yield (lambda (value) (lambda (yc) (set! yield-continuation yc) (caller-continuation value)))))) body ...)] ))))))))

30 Let's macroize it (define (fibs) (generator (let loop ((greater 1)
(lesser 0)) (yield greater) (loop (+ greater lesser) greater))))

31 Let's macroize it (define (fibs) (generator (let loop ((greater 1)
(lesser 0)) (yield greater) (loop (+ greater lesser) greater)))) ■ yield: unbound identifier in module

32 Let's macroize it (define-syntax generator (syntax-rules ()
((generator body ...) (let ((yield-continuation #f)) (lambda () (call-with-current-continuation (lambda (caller-continuation) (cond [yield-continuation (yield-continuation #t)] [else (let ((yield (lambda (value) (lambda (yc) (set! yield-continuation yc) (caller-continuation value)))))) body ...)] ))))))))

33 Let's macroize it (define-syntax generator (syntax-rules ()
((generator yield body ...) (let ((yield-continuation #f)) (lambda () (call-with-current-continuation (lambda (caller-continuation) (cond [yield-continuation (yield-continuation #t)] [else (let ((yield (lambda (value) (lambda (yc) (set! yield-continuation yc) (caller-continuation value)))))) body ...)] ))))))))

34 Let's macroize it At least we can choose yield's name...
(define (fibs) (generator yield (let loop ((greater 1) (lesser 0)) (yield greater) (loop (+ greater lesser) greater)))) At least we can choose yield's name... By the way, yield is a first-class procedure which we can pass around...

35 Now it looks pretty (define (list->generator ls) (generator yield (for-each yield ls))) ▶ (define g (list->generator (list ))) ▶ (g) 1 ▶ (g) 2 3 4 5

36 Huh... (define (list->generator ls) (generator yield (for-each yield ls))) ▶ (define g (list->generator (list ))) ▶ (g) 1 ▶ (g) 2 3 4 5

37 Huh?! (define (list->generator ls) (generator yield (for-each yield ls))) ▶ (define g (list->generator (list ))) ▶ (g) 1 ▶ (g) 2 3 4 5 ▶ (list (g))

38 WTF (define (list->generator ls) (generator yield (for-each yield ls))) ▶ (define g (list->generator (list ))) ▶ (list (g) (g) (g)) ... infinite loop ...

39 The dangers of continuations
(define-syntax generator (syntax-rules () ((generator yield body ...) (let ((yield-continuation #f)) (lambda () (call-with-current-continuation (lambda (caller-continuation) (cond [yield-continuation (yield-continuation #t)] [else (let ((yield (lambda (value) (lambda (yc) (set! yield-continuation yc) (caller-continuation value)))))) body ...)] ))))))))

40 The dangers of continuations
(define-syntax generator (syntax-rules () ((generator yield body ...) (let ((yield-continuation #f)) (lambda () (call-with-current-continuation (lambda (caller-continuation) (cond [yield-continuation (yield-continuation #t)] [else (let ((yield (lambda (value) (lambda (yc) (set! yield-continuation yc) (caller-continuation value)))))) body ...)] )))))))) chamada ao gerador captura a continuação do chamador em uma variável local nova

41 The dangers of continuations
(define-syntax generator (syntax-rules () ((generator yield body ...) (let ((yield-continuation #f)) (lambda () (call-with-current-continuation (lambda (caller-continuation) (cond [yield-continuation (yield-continuation #t)] [else (let ((yield (lambda (value) (lambda (yc) (set! yield-continuation yc) (caller-continuation value)))))) body ...)] )))))))) chamada ao gerador captura a continuação do chamador em uma variável local nova não é a mesma que estava ativa quando a continuação de yield foi salva!

42 The dangers of continuations
(define-syntax generator (syntax-rules () ((generator yield body ...) (let ((yield-continuation #f) (caller-continuation #f)) (lambda () (call-with-current-continuation (lambda (cc) (set! caller-continuation cc) (cond [yield-continuation (yield-continuation #t)] [else (let ((yield (lambda (value) (lambda (yc) (set! yield-continuation yc) (caller-continuation value)))))) body ...)] )))))))) variável compartilhada entre todas as chamadas ao gerador altera variável existente ao invés de criar nova

43 Now it looks pretty (define (list->generator ls) (generator yield (for-each yield ls))) ▶ (define g (list->generator (list ))) ▶ (list (g) (g) (g)) (1 2 3)

44 O RLY? (define (list->generator ls) (generator yield (for-each yield ls))) ▶ (define g (list->generator (list ))) ▶ (list (g) (g) (g) (g)) ... infinite loop ...

45 O RLY? (define (list->generator ls) (generator yield (for-each yield ls))) ▶ (define g (list->generator (list ))) ▶ (list (g) (g) (g) (g)) ... infinite loop ... Problema: yield só é chamada três vezes Última chamada foi a que retornou valor do terceiro argumento de list Essa é a última continuação salva! Solução: Adicionar código à macro que limpe a continuação salva Sugerido como exercício para o leitor

46 Continuation Passing Style
function foo(n) { return(n*n); } ▶ 1 + foo(3) 10 return(x) = 1 + x return = λx. 1 + x

47 Continuation Passing Style
function foo(n, return) { return(n*n); } ▶ foo(1, λx -> 1 + x) 10

48 Continuation Passing Style
É possível reescrever as funções para receberem sua continuação explicitamente como um argumento Usado como passo de transformação em alguns compiladores de linguagens funcionais Dá nome aos valores de retorno (temporários) Define a ordem de avaliação explicitamente Reifica a continuação (= call/cc) f(g(x), h(y)) λk -> g(x, λtmp1 -> h(y, λtmp2 -> f(tmp1, tmp2, k))) Sure I won't write code like this Mas funciona em qualquer linguagem com closures Além disso, tem algo de familiar nesse código...

49 Continuation Passing Style
function foo(n, return) { return(n*n); } ▶ foo(1, λx -> 1 + x) 10

50 Continuation Passing Style
foo n k = k (n*n :: Int) ▶ foo 3 (\x -> 1 + x) 10

51 Continuation Passing Style
foo n k = k (n*n :: Int) ▶ foo 3 (\x -> 1 + x) 10 ▶ :t foo 3 foo 3 :: (Int -> t) -> t ▶ :t foo foo :: Int -> (Int -> t) -> t

52 Continuation Passing Style
foo n k = k (n*n :: Int) ▶ foo 3 (\x -> 1 + x) 10 ▶ :t foo 3 foo 3 :: (Int -> t) -> t ▶ :t foo foo :: Int -> (Int -> t) -> t m a a -> mb ???

53 Continuation Passing Style
foo n k = k (n*n :: Int) ▶ foo 3 (\x -> 1 + x) 10 ▶ :t foo 3 foo 3 :: (Int -> t) -> t ▶ :t foo foo :: Int -> (Int -> t) -> t \k -> g x (\tmp1 -> h y (\tmp2 -> f tmp1 tmp2 k)) m a a -> mb ???

54 Continuation Passing Style
foo n k = k (n*n :: Int) ▶ foo 3 (\x -> 1 + x) 10 ▶ :t foo 3 foo 3 :: (Int -> t) -> t ▶ :t foo foo :: Int -> (Int -> t) -> t \k -> g x $ (\tmp1 -> h y $ (\tmp2 -> f tmp1 tmp2 k)) m a a -> mb ???

55 Continuation Passing Style
foo n k = k (n*n :: Int) ▶ foo 3 (\x -> 1 + x) 10 ▶ :t foo 3 foo 3 :: (Int -> t) -> t ▶ :t foo foo :: Int -> (Int -> t) -> t \k -> g x >>= (\tmp1 -> h y >>= (\tmp2 -> f tmp1 tmp2 k)) ??? m a a -> mb ???

56 Continuation Passing Style
foo n k = k (n*n :: Int) ▶ foo 3 (\x -> 1 + x) 10 ▶ :t foo 3 foo 3 :: (Int -> t) -> t ▶ :t foo foo :: Int -> (Int -> t) -> t \k -> g x >>= (\tmp1 -> h y >>= (\tmp2 -> f tmp1 tmp2 k)) ??? do tmp1 <- g x tmp2 <- h y return f tmp1 tmp2 m a a -> mb ???

57 Continuation Passing Style
foo n k = k (n*n :: Int) ▶ foo 3 (\x -> 1 + x) 10 ▶ :t foo 3 foo 3 :: (Int -> t) -> t ▶ :t foo foo :: Int -> (Int -> t) -> t \k -> g x >>= (\tmp1 -> h y >>= (\tmp2 -> f tmp1 tmp2 k)) ??? do tmp1 <- g x tmp2 <- h y return f tmp1 tmp2 Sugerido como exercício para o leitor m a a -> mb ???

58 Conclusão Continuations Representam computação "por realizar"
Mother of all control structures Diversas aplicações Escapes Generators Não-determinismo Easy to misuse Normalmente usadas para construir abstrações mais bem-comportadas Continuation-passing style Yet another monad


Carregar ppt "Continuations Programação Funcional Avançada Vítor De Araújo"

Apresentações semelhantes


Anúncios Google