Slide 1

Slide 1 text

ANA LUIZA BASTOS github.com/anabastos @naluhh @anapbastos Fullstack Developer na Quanto e cientista da computação na PUC-SP anabastos.me

Slide 2

Slide 2 text

JSLADIES fb.com/jsladiesbr twitter.com/jsladiessp meetup.com/JsLadies-BR/ LAMBDA.IO t.me/lambdastudygroup github.com/lambda-study-group/ meetup.com/Lambda-I-O-Sampa- Meetup/

Slide 3

Slide 3 text

VISÃO GERAL SOBRE RECURSÃO & TRAMPOLINES

Slide 4

Slide 4 text

VAMOS FALAR SOBRE RECURSÃO

Slide 5

Slide 5 text

Recursão é quando uma função chama a si mesma até uma condição parar o loop.

Slide 6

Slide 6 text

λ Programação Funcional

Slide 7

Slide 7 text

Fatorial 1! = 1 3! = 1 * 2 * 3 = 6

Slide 8

Slide 8 text

const iterativeFactorial = (n) => { let i let contador = 0 for (i = 1; i <= n; i++) { contador *= i } return contador }

Slide 9

Slide 9 text

1. Qual parte do código é recursiva 2. Condição de saída

Slide 10

Slide 10 text

const fac = (n) => { if (n == 0) { return 1 } return n * fac(n - 1) }

Slide 11

Slide 11 text

● EXPRESSIVO ● PURO / EVITANDO MUDANÇA DE ESTADO(CONTADOR) ● IMUTABILIDADE DE DADOS ● DECLARATIVO ● IDEMPOTENCIA

Slide 12

Slide 12 text

JS é single threaded e orientado a stack

Slide 13

Slide 13 text

No content

Slide 14

Slide 14 text

GC fac(3) GC fac(2) fac(3) GC fac(1) fac(2) fac(3) GC fac(0) fac(1) fac(2) fac(3) GC call call call call

Slide 15

Slide 15 text

GC fac(3) GC fac(2) fac(3) GC fac(1) fac(2) fac(3) GC fac(0) fac(1) fac(2) fac(3) GC 1 1* 1 = 1 1 * 2 = 2 2 * 3 = 6

Slide 16

Slide 16 text

GC fac(9999) GC fac(9998) fac(9999) GC fac(9997) fac(9998) fac(9999) GC oh no ... fac(9998) fac(9999) GC StackOverFlow :(

Slide 17

Slide 17 text

Cruza os dedos? Senta e chora?

Slide 18

Slide 18 text

TAIL CALL OPTIMIZATION (TCO)

Slide 19

Slide 19 text

Truque antigo

Slide 20

Slide 20 text

GC fac(3) GC fac(2) fac(3) GC fac(1) fac(2) fac(3) GC fac(0) fac(1) fac(2) fac(3) GC call call call call

Slide 21

Slide 21 text

TCO faz com que a gente evite explodir o stack quando fazemos chamadas recursivas

Slide 22

Slide 22 text

PROPER TAIL CALLS (PTC)

Slide 23

Slide 23 text

Possibilita que sua função recursiva seja otimizada pela engine.

Slide 24

Slide 24 text

RECURSÃO EM CAUDA (TAIL CALL)

Slide 25

Slide 25 text

//Não é tail call :( const fac = (n) => n == 0 ? 1 : n * fac(n - 1)

Slide 26

Slide 26 text

A última coisa a ser feita na função é o retorno da própria função.

Slide 27

Slide 27 text

Acumulador

Slide 28

Slide 28 text

const tailRecursiveFac = (n, acc = 1) => { return n == 0 ? acc : tailRecursiveFac(n - 1, acc * n) }

Slide 29

Slide 29 text

ES6 http://www.ecma-international.org/ecma-262/6.0/#sec-tail-position- calls

Slide 30

Slide 30 text

No content

Slide 31

Slide 31 text

Além disso existem casos de algoritmos que precisam de mais de duas chamadas recursivas(multiple recursion) e não tem como colocar tudo no final

Slide 32

Slide 32 text

COMO LIDAR COM ISSO?

Slide 33

Slide 33 text

CONTINUATION PASSING STYLE (CPS)

Slide 34

Slide 34 text

Um estilo de programação em que o controle é passado explicitamente em forma de continuação

Slide 35

Slide 35 text

Continuação é uma parte de código que ainda vai ser executada em algum ponto do programa Callbacks por exemplo são continuations

Slide 36

Slide 36 text

Continuação não chama a si mesma, ela só expressa um fluxo de computação onde os resultados fluem em uma direção. Aplicar continuações não é chamar funções é passar o controle do resultado.

Slide 37

Slide 37 text

LAZY EVALUATION

Slide 38

Slide 38 text

CALL-BY-NEED

Slide 39

Slide 39 text

> (1 + 3) * 2 8 > const expression = () => (1 + 3) * 2 > expression() 8

Slide 40

Slide 40 text

Ou seja, o programa espera receber os dados antes de continuar.

Slide 41

Slide 41 text

E daí?

Slide 42

Slide 42 text

CPS elimina a necessidade de um call stack pois os valores estarão dentro da continuation sendo executada .

Slide 43

Slide 43 text

Acumulador para uma continuação

Slide 44

Slide 44 text

IDENTITY FUNCTION

Slide 45

Slide 45 text

const id = x => x

Slide 46

Slide 46 text

● O último parâmetro da função é sempre a continuation. ● Todas as funções precisam acabar chamando sua continuação com o resultado da execução da função.

Slide 47

Slide 47 text

const cpsFac = (n, con) => { return n == 0 ? con(1) : cpsFac(n - 1, y => con(n + y)) } cpsFac(3, id) //6

Slide 48

Slide 48 text

TRAMPOLINES

Slide 49

Slide 49 text

Técnica stack safe para fazer chamadas tail-recursive em linguagens orientadas a stack

Slide 50

Slide 50 text

Um trampoline é um loop que iterativamente invoca funções que retornam thunks (continuation-passing style)

Slide 51

Slide 51 text

THUNKS

Slide 52

Slide 52 text

Função que encapsula outra função com os parâmetros que para quando a execução dessa função for necessária.

Slide 53

Slide 53 text

function thunk(fn, args) { return fn(...args) }

Slide 54

Slide 54 text

Ao invés de chamar a tail call diretamente, cada método retorna a chamada para um thunk para o trampolim chamar.

Slide 55

Slide 55 text

const trampoline = (thunk) => { while(thunk instanceof Function){ thunk = thunk() } return thunk }

Slide 56

Slide 56 text

● É um loop que chama funções repetidamente ● Cada função é chamada de thunk. ● O trampolim nunca chama mais de um thunk ● É como se quebrasse o programa em pequenos thunks que saltam pra fora do trampolim, assim o stack não cresce.

Slide 57

Slide 57 text

const trampolineFac = (n) { const fac = (n, ac = 1) => { return n == 0 ? ac : thunk(fac, n - 1, ac * n) } return trampoline(thunk(fac, n, 1)) }

Slide 58

Slide 58 text

GC fac(3) GC call GC fac(2) GC GC bounce bounce

Slide 59

Slide 59 text

:(

Slide 60

Slide 60 text

Trade off por stack safety Trocamos o trabalho de criar stack frames com o de criar binding de funções.

Slide 61

Slide 61 text

Em muitos casos o trade-off de overhead por expressividade vale a pena

Slide 62

Slide 62 text

Trampolines são mais apropriadas para funções complexas em que não existem soluções iterativas e não conflitam com outras técnicas de mediar controle de fluxo(Promises).

Slide 63

Slide 63 text

● Kyle Simpson. Functional Light Programming. Cap 8. - github.com/getify/Functional-Light-JS ● Functional Programming Jargon - github.com/hemanth/functional-programming-jarg on ● Structure and Interpretation of Computer Programs - Javascript Adaptation

Slide 64

Slide 64 text

● Compatibilidade TCO - kangax.github.io/compat-table/es6/#test-proper_tail_c alls_ ● Yoyojs - npmjs.com/package/yoyojs ● Ramda Memoisation - ramdajs.com/docs/#memoize

Slide 65

Slide 65 text

t.me/lambdastudygroup github.com/lambda-study-group

Slide 66

Slide 66 text

OBRIGADA :) https://speakerdeck.com/anabastos