Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
ANA LUIZA BASTOS
github.com/anabastos
@naluhh
@anapbastos
Software Developer na Quanto e
cientista da computação da
PUC-SP...
JSLADIES
fb.com/jsladiesbr
twitter.com/jsladiessp
meetup.com/JsLadies-BR/
LAMBDA.IO
t.me/lambdastudygroup
github.com/lambd...
VISÃO GERAL SOBRE
RECURSÃO &
TRAMPOLINES
VAMOS FALAR SOBRE
RECURSÃO
Recursão é quando uma função
chama a si mesma até uma condição parar o
loop.
λ Programação Funcional
Fatorial
1! = 1
3! = 1 * 2 * 3 = 6
1. Qual parte do código é
recursiva
2. Condição de saída
const fac = (n) => {
if (n == 0) {
return 1
}
return n * fac(n - 1)
}
● EXPRESSIVO
● PURO / EVITANDO MUDANÇA DE
ESTADO(CONTADOR)
● IMUTABILIDADE DE DADOS
● DECLARATIVO
● IDEMPOTENCIA
JS é single threaded
e orientado a stack
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
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
GC
fac(9999)
GC
fac(9998)
fac(9999)
GC
fac(9997)
fac(9998)
fac(9999)
GC
oh no
...
fac(9998)
fac(9999)
GC
StackOverFlow :(
Cruza os dedos?
Senta e chora?
TAIL CALL OPTIMIZATION
(TCO)
Truque antigo que muitas
linguagens funcionais fazem
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
TCO faz com que a gente evite
explodir o stack quando
fazemos chamadas recursivas
PROPER TAIL CALLS
(PTC)
Possibilita que sua função
recursiva seja otimizada pela
engine.
RECURSÃO EM CAUDA
(TAIL CALL)
//Não é tail call :(
const fac = (n) => n == 0
? 1
: n * fac(n - 1)
A última coisa a ser feita na função
é o retorno da própria função.
Acumulador
const tailRecursiveFac = (n, acc = 1) => {
return n == 0
? acc
: tailRecursiveFac(n - 1, acc +
n)
}
ES6
http://www.ecma-international.org/ecma-262/6.0/#sec-tail-position-
calls
Além disso existem casos de
algoritmos que precisam de mais
de duas chamadas
recursivas(multiple recursion) e não
tem como...
COMO LIDAR COM ISSO?
CONTINUATION PASSING
STYLE (CPS)
Um estilo de programação em que
o controle é passado explicitamente
em forma de continuação
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ção é uma parte de
código que ainda vai ser executada
em algum ponto do programa
Callbacks por exemplo são continu...
LAZY EVALUATION
CALL-BY-NEED
> (1 + 3) * 2
8
> const expression = () => (1 + 3) * 2
> expression()
8
Ou seja, o programa espera receber os
dados antes de continuar.
E daí?
CPS elimina a necessidade de um
call stack pois os valores estarão
dentro da continuation sendo
executada .
Acumulador para uma
continuação
IDENTITY FUNCTION
const id = x => x
● O último parâmetro da função é sempre a
continuation.
● Todas as funções precisam acabar chamando
sua continuação com o ...
const cpsFac = (n, con) => {
return n == 0
? con(1)
: cpsFac(n - 1, y =>
con(n + y))
}
cpsFac(3, id) //6
TRAMPOLINES
Técnica stack safe pra fazer
chamadas tail-recursive em
linguagens orientadas a stack
Um único trampoline consegue expressar
todas as transferência de controle do
programa.
Um trampoline é um loop
que iterativamente invoca
funções que retornam thunks
(continuation-passing style)
THUNKS
Função que encapsula outra
função com os parâmetros que
para quando a execução dessa
função for necessária.
function thunk(fn, args) {
return fn(...args)
}
Ao invés de chamar a tail call
diretamente, cada método retorna
a chamada para um thunk para o
trampolim chamar.
const trampoline = (thunk) => {
while(thunk instanceof Function){
thunk = thunk()
}
return thunk
}
● É um loop que chama funções repetidamente
● Cada função é chamada de thunk.
● O trampolim nunca chama mais de um thunk
●...
const trampolineFac = (n) {
const sum = (ac, n) => {
return n == 0
? ac
: thunk(sum, ac * n, n -
1)
}
return trampoline(th...
GC
sum(3)
GC GC
sum(2)
GC GC
:(
Trade off por stack safety
Trocamos o trabalho de criar stack frames com
o de criar binding de funções.
Em muitos casos o trade-off de
overhead por expressividade vale a
pena
Trampolines são mais apropriadas
para funções complexas em que não
existem soluções iterativas e não
conflitam com outras ...
● Kyle Simpson. Functional Light Programming. Cap
8. - github.com/getify/Functional-Light-JS
● Functional Programming Jarg...
● Compatibilidade TCO -
kangax.github.io/compat-table/es6/#test-
proper_tail_calls_
● Yoyojs - npmjs.com/package/yoyojs
● ...
t.me/lambdastudygroup
github.com/lambda-study-group
OBRIGADA :)
https://speakerdeck.com/anabastos
[JS EXPERIENCE 2018] Uma visão geral sobre recursão e trampolines - Ana Bastos, Quanto
[JS EXPERIENCE 2018] Uma visão geral sobre recursão e trampolines - Ana Bastos, Quanto
Upcoming SlideShare
Loading in …5
×

[JS EXPERIENCE 2018] Uma visão geral sobre recursão e trampolines - Ana Bastos, Quanto

133 views

Published on

Uma visão geral sobre recursão e trampolines - Ana Bastos, Quanto

[JS EXPERIENCE 2018] - 5 de julho de 2018
São Paulo/SP

Published in: Technology
  • Be the first to comment

[JS EXPERIENCE 2018] Uma visão geral sobre recursão e trampolines - Ana Bastos, Quanto

  1. 1. ANA LUIZA BASTOS github.com/anabastos @naluhh @anapbastos Software Developer na Quanto e cientista da computação da PUC-SP anabastos.me
  2. 2. 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/
  3. 3. VISÃO GERAL SOBRE RECURSÃO & TRAMPOLINES
  4. 4. VAMOS FALAR SOBRE RECURSÃO
  5. 5. Recursão é quando uma função chama a si mesma até uma condição parar o loop.
  6. 6. λ Programação Funcional
  7. 7. Fatorial 1! = 1 3! = 1 * 2 * 3 = 6
  8. 8. 1. Qual parte do código é recursiva 2. Condição de saída
  9. 9. const fac = (n) => { if (n == 0) { return 1 } return n * fac(n - 1) }
  10. 10. ● EXPRESSIVO ● PURO / EVITANDO MUDANÇA DE ESTADO(CONTADOR) ● IMUTABILIDADE DE DADOS ● DECLARATIVO ● IDEMPOTENCIA
  11. 11. JS é single threaded e orientado a stack
  12. 12. 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
  13. 13. 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
  14. 14. GC fac(9999) GC fac(9998) fac(9999) GC fac(9997) fac(9998) fac(9999) GC oh no ... fac(9998) fac(9999) GC StackOverFlow :(
  15. 15. Cruza os dedos? Senta e chora?
  16. 16. TAIL CALL OPTIMIZATION (TCO)
  17. 17. Truque antigo que muitas linguagens funcionais fazem
  18. 18. 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
  19. 19. TCO faz com que a gente evite explodir o stack quando fazemos chamadas recursivas
  20. 20. PROPER TAIL CALLS (PTC)
  21. 21. Possibilita que sua função recursiva seja otimizada pela engine.
  22. 22. RECURSÃO EM CAUDA (TAIL CALL)
  23. 23. //Não é tail call :( const fac = (n) => n == 0 ? 1 : n * fac(n - 1)
  24. 24. A última coisa a ser feita na função é o retorno da própria função.
  25. 25. Acumulador
  26. 26. const tailRecursiveFac = (n, acc = 1) => { return n == 0 ? acc : tailRecursiveFac(n - 1, acc + n) }
  27. 27. ES6 http://www.ecma-international.org/ecma-262/6.0/#sec-tail-position- calls
  28. 28. 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
  29. 29. COMO LIDAR COM ISSO?
  30. 30. CONTINUATION PASSING STYLE (CPS)
  31. 31. Um estilo de programação em que o controle é passado explicitamente em forma de continuação
  32. 32. 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.
  33. 33. Continuação é uma parte de código que ainda vai ser executada em algum ponto do programa Callbacks por exemplo são continuations
  34. 34. LAZY EVALUATION
  35. 35. CALL-BY-NEED
  36. 36. > (1 + 3) * 2 8 > const expression = () => (1 + 3) * 2 > expression() 8
  37. 37. Ou seja, o programa espera receber os dados antes de continuar.
  38. 38. E daí?
  39. 39. CPS elimina a necessidade de um call stack pois os valores estarão dentro da continuation sendo executada .
  40. 40. Acumulador para uma continuação
  41. 41. IDENTITY FUNCTION
  42. 42. const id = x => x
  43. 43. ● 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.
  44. 44. const cpsFac = (n, con) => { return n == 0 ? con(1) : cpsFac(n - 1, y => con(n + y)) } cpsFac(3, id) //6
  45. 45. TRAMPOLINES
  46. 46. Técnica stack safe pra fazer chamadas tail-recursive em linguagens orientadas a stack
  47. 47. Um único trampoline consegue expressar todas as transferência de controle do programa.
  48. 48. Um trampoline é um loop que iterativamente invoca funções que retornam thunks (continuation-passing style)
  49. 49. THUNKS
  50. 50. Função que encapsula outra função com os parâmetros que para quando a execução dessa função for necessária.
  51. 51. function thunk(fn, args) { return fn(...args) }
  52. 52. Ao invés de chamar a tail call diretamente, cada método retorna a chamada para um thunk para o trampolim chamar.
  53. 53. const trampoline = (thunk) => { while(thunk instanceof Function){ thunk = thunk() } return thunk }
  54. 54. ● É 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.
  55. 55. const trampolineFac = (n) { const sum = (ac, n) => { return n == 0 ? ac : thunk(sum, ac * n, n - 1) } return trampoline(thunk(sum, n, 0)) }
  56. 56. GC sum(3) GC GC sum(2) GC GC
  57. 57. :(
  58. 58. Trade off por stack safety Trocamos o trabalho de criar stack frames com o de criar binding de funções.
  59. 59. Em muitos casos o trade-off de overhead por expressividade vale a pena
  60. 60. 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).
  61. 61. ● Kyle Simpson. Functional Light Programming. Cap 8. - github.com/getify/Functional-Light-JS ● Functional Programming Jargon - github.com/hemanth/functional-programming- jargon ● Structure and Interpretation of Computer Programs - Javascript Adaptation
  62. 62. ● Compatibilidade TCO - kangax.github.io/compat-table/es6/#test- proper_tail_calls_ ● Yoyojs - npmjs.com/package/yoyojs ● Ramda Memoisation - ramdajs.com/docs/#memoize
  63. 63. t.me/lambdastudygroup github.com/lambda-study-group
  64. 64. OBRIGADA :) https://speakerdeck.com/anabastos

×