JavaScriptPeter Borovanský, KAI, I-18, borovan(a)ii.fmph.uniba.sk
http://dai.fmph.uniba.sk/courses/PARA/alias: digmy(a)lists.dai.fmph.uniba.sk
Pon, 12:20, M-XII
Zdroje:Douglas Crockford: JavaScript: The Good Parts•autor json konceptu•JSLint
Obsahn Statické a dynamické typovanie, rôzne odtiene (1./3)n Good & bad parts of Javascript (ES6) (2./3)n scopen clojuren python generator pomocou clojuresn tail recursion optimisation, tail calls (3./3)n trampolinan continuation Passing Style vs. callback
JSn Či chcete, alebo nie, Javascript je assembler internetu,
n Pri písaní aplikácií sa mu nedá vyhnúť, viete ho len zakryť frameworkom/ iným (napr. typovaným) jazykom, ktorý vám nakoniec JS vygeneruje,
n JS chýbajú typy,
n môžete v ňom začať písať aj bez príručky, je natoľko intuitívny,
n a o to viac zradný (najmä pre C++/Java programátora),
n môžete ho milovať alebo nenávidieť, nič medzi ☺
JS má špecifikáciu(ES6)
n 550 strán pomerne nudného čítania, reference manual
https://www.google.sk/url?sa=t&rct=j&q=&esrc=s&source=web&cd=1&ved=0ahUKEwinofLsm7bWAhXI0hoKHSXADvcQFggmMAA&url=https%3A%2F%2
Learn ES2015(ES 6 features based on Hoban's es6features repo)
n 550 strán pomerne nudného čítania, reference manual
https://babeljs.io/learn-es2015/#ecmascript-2015-features-tail-calls
JS má rôzne implementácie(ES6)
http://kangax.github.io/compat-table/es6/
JavaScript: The Good Parts(Douglas Crockford)
If a feature is sometimes useful and sometimes dangerous, and if there is abetter option, then always use the better option.
We are not paid to use every feature of the language.We are paid to write programs that work well and are free of errors.
A good programming language should teach you.
It took a generation to agree that:n high level languages were a good idea,n goto statement was a bad idea,n objects were a good idea,n lambdas (functions) were a good idea.
Ako to začalo(dnes je to JavaScript ES6)
n interactive language for Netscapen LiveScript: 10 dní na prototyp vychádzajúci z:
n Java - syntax, aj kus názvu jazykan Scheme/Lisp – lambdas – funkcie a functionálny pohľad, n Self/Smalltalk – Smalltalk bez tried.
n 1995, zároveň sa úspešne rozvíja Goslingova Javan Silná spoločná motivácia pre JS a Java: byť nezávislý od platformy Microsoft
ten si vyvýja Jscript(Active Script), J++
n Súboj Java Appletov a JavaScript vyhráva JS na plnej čiare
n Na úvodné programovanie v JS nepotrebujete čítať žiadnu obsiahlu dokumentáciu
n Stačí si otvoriť konzolu od browsera (alebo repl.it) a “programujete”
Brendan Eich
Statici vs. dynamiciExistuje večná vojna medzi dynamickými a statickými programátormi.Je fajn zistiť, o čom je táto vojna...
Dynamicky typované jazyky: typ premennej sa určí počas behu, podľa hodnotyktorá sa v premennej nachádza, príklad PHP, Groovy, JRuby, JavaScript, ...Typ (aritmetickej) operácie sa určí z typov operandov.
Staticky typované jazyky: typ premennej sa určí, resp. je známy, už počas kompilácie, príklad C++, Java, ...
Statický môže byť aj jazyk, ktorý nevyžaduje typy tak rigidne ako C++ alebo Java.Z aktuálnych príkladov, Haskell, Go, Scala, Swift, Kotlin...Typová inferencia (u statických jazykov) je, ak jazyk/kompilátor vie zistiť typ premennej bez toho, aby ho programátor musel explicitne písať/deklarovať,príklad Scala, Kotlin, Haskell, ...
C++(Java) vs. Python(JavaScript)n kým C++ (Java) oplýva komplikovanosťou
a ťažkopádnosťou často spôsobenoustatickou typovou kontrolou, interpretované a dynamicky typované jazyky ako Python, Ruby, JavaScript ponúkajú ľahkosť, elegantnosť pri písaní, kódu, malých prototypov.-- aj preto si ich ľudia veľmi obľúbili
n dynamické typovanie je ale smrť pre väčšie projekty-- osobný názor, s ktorým môžete nesúhlasiť...
n tradičné kompilované (staticky typované) jazyky ako C, C++, Delphi (Java) ponúkajú efektívnosť na úkor pohodlia pri písaní kódu
Go chce uspieť ako:n efektívny (t.j. kompilovaný) jazyk vhodný pre veľké projektyn s rýchlym kompilátoromn ako jazyk s podporou distribuovaných, konkurentných a sieťových aplikácií
http://www.tiobe.com/index.php/content/paperinfo/tpci/index.html
Typovanien Dynamicky typovaný jazyk – typ premennej môže byť zmenený
kedykoľvek na iný, napr. reťazec, int, time, objekt, ...n Staticky typovaný jazyk – typ premennej je raz pre vždy určený a nemenný
napr. deklaráciou, alebo prvým výskytom (Explicitne/Implicitne)_____________________________________________________n Silne (strong) typovaný jazyk – striknte určuje operácie, ktoré môžete s
typovanou premennou, nesmiete miešať typy, inak nastane výnimkan Slabo (weakly) typovaný jazyk – možete robiť čokolvek s rôznymi typmi,
miešať ich, nenastane výnimka
http://blogs.perl.org/users/ovid/2010/08/what-to-know-before-debating-type-systems.html
Javascript L
Slabé typovanien no typing - assemblern weak static typing (C, C++, Objective C)
char z = “hello”; // núti definovať typy všetkých objektov, ale interne… // si pamätá, koľko bajtov zaberáprintf(“%i”,z); // keď ju chceme formátovať, treba pripomenúť typ
viac a viac typových obmedzení počas času kompilácie (C->C++)
Čo je 749711097 ?n 749711097 = 249903699 * 3 n 74 97 110 97 = “Jana” n 74 9711097 = GMT: Monday 4. October 1993 5:04:57
http://coding.smashingmagazine.com/2013/04/18/introduction-to-programming-type-systems/
char z = 'A'; printf("%d, %c", z, z);65, A
Silné statické typovanien strong static typing (Java)
informácia o type je prístupná v čase behu, a VM teda môže kontrolovať typak chceme pretypovať objekt na iný typ, Java v čase behu realizuje kontroluvýsledok: menej hackov ako C, C++, jazyk je viac rigidnejší
public class Person {public String getName() {
return "zack";}
} // mimo classy nemôžeme definovať žiaden kódpublic class Main {
public static void main (String args[]) {Person person = new Person();System.out.println("The name is " + person.getName());
}} zdroj:http://coding.smashingmagazine.com/2013/04/18/introduction-to-programming-type-systems/
Silné dynamické typovanien strong dynamic typing (JS, Python, Ruby)
var person = {getName: function() {
return 'zack';}
};if (new Date().getMinutes() > 29) {
person = 5;}alert('The name is ' + person.getName());
zdroj:http://coding.smashingmagazine.com/2013/04/18/introduction-to-programming-type-systems/
Silné dynamické typovanien strong dynamic typing (JS, Python, Ruby)
if (new Date().getMinutes() > 29): z = “aaa”
else: z = 5
print zz = z+z // typ z sa zisťuje až v čase behu programu
// - pol hodinu je to String + String// - a pol hodinu int + int
zdroj:http://coding.smashingmagazine.com/2013/04/18/introduction-to-programming-type-systems/
Duck typingn duck typing (JS, Python, Ruby)
var person = {getName: function() { return 'zack'; }
};person['getBirthday'] = function() { return 'July 18th'; };
person['getName'] = 5; // person.getName is not a functionperson['getName'] = null; // person.getName is not a functionperson['getName'] = undefined; // person.getName is not a function
console.log('The name is ' + person.getName() + ' ' +'and the birthday is ' + person.getBirthday());
http://coding.smashingmagazine.com/2013/04/18/introduction-to-programming-type-systems/
if it walks like a duck and quacks like a duck, then it must be a duck.
Objekt patrí do tej triedy ako kváka...
Statici vs. Dynamici(vojnové argumenty)
“Static typing catches bugs with the compiler and keeps you out of trouble.”
“Static languages are easier to read because they’re more explicit about what the code does.”
“At least I know that the code compiles.”
“I trust the static typing to make sure my team writes good code.”
http://coding.smashingmagazine.com/2013/04/18/introduction-to-programming-type-systems/
“Static typing only catches some bugs, and you can’t trust the compiler to do your testing.”
“Dynamic languages are easier to read because you write less code.”
“Just because the code compiles doesn’t mean it runs.”
“The compiler doesn’t stop you from writing bad code.”
0.1 + 0.2 == 0.3if (0.1 + 0.2 == 0.3) {console.log(":-)");
} else {console.log(":-(");
}
if (0.1 + 0.2 == 0.3): print(":-)");
else: print(":-(");
#include <iostream>int main() { if (0.1 + 0.2 == 0.3) { std::cout << ":-)";
} else { std::cout << ":-(";
}}
main = do if (0.1 + 0.2 == 0.3) then
putStrLn ":-)" else
putStrLn ":-("
(1 ÷ 10)+(2 ÷ 10)-(3 ÷ 10)
Viacznačnosť zabíja
Ambiguita je smrť !
Perfection is achieved, not when there is nothing more to add, but when there is nothing left to take away-- Antoine de Saint-Exupery
ASCII: (viacznačnosť zabíja)
n TAB vs. SPACE
n ’ vs. ”n alert('wow')n alert("WOW")
n UPPERCASE vs. lowercase ( ↑ , ↓)n case sensitivity vznikla s ASCII-7
https://www.youtube.com/watch?v=SsoOG6ZeyUI Richard HendrixHBO Silicon Valley SE03
var vs. letfunction varTest() {var x = 1;if (true) {var x = 2; // rovnaká premenná, var ignoruje block-scopeconsole.log(x); // 2
}console.log(x); // 2 – tvrdá rana pre programátora vyškoleného
} v C, C++, Java, ...function letTest() {let x = 1;if (true) {let x = 2; // rôzne premennéx = x+1; // premenná definovaná let je modifikovateľnáconsole.log(x); // 3
}console.log(x); // 1
}https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let
const vs. letfunction constTest() {const x = 1;if (true) {const x = 2; // rôzne premenné// x = x+1;console.log(x); // 2
}console.log(x); // 1
}
Množstvo konštánt, ktoré používame v programoch, definujeme ako premenné s inicializáciou a nikdy nezmeníme.
Pritom const je konštrukcia deklarujúca, že niečo sa nebude meniť.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/const
null vs. undefined(javascript unikát)
n JS má dve hodnoty pre nedefinovanú hodnotun null a undefined
n typeof 12 'number'n typeof 'wow' 'string'n typeof null 'object'???n typeof undefined 'undefined'
NULL (okrem iných vecí ako QuickSort, CSP, ...) objavil/zaviedol Tony Hoarepre nedokonalosť typového systému vtedy Algolu.Dnešné jazyky (Swift, Kotlin) to riešia typmi String (never null), String?
2009, he apologised for inventing the null reference:[20]
I call it my billion-dollar mistake. It was the invention of the null reference in 1965. At that time, I was designing the first comprehensive type systemfor references in an object oriented language (ALGOLW). My goal was to ensure that all use of references should beabsolutely safe, with checking performed automatically by the compiler. But I couldn't resist the temptation to put ina null reference, simply because it was so easy to implement. This has led to innumerable errors, vulnerabilities,and system crashes, which have probably caused a billion dollars of pain and damage in the last forty years.
Tony Hoare
= vs. == vs. ===(jediný jazyk, kde == nie je tranzitívne)
n 0 == '' // true, platí aj opačnen 0 == '0' // true, platí aj opačnen '' == '0' // false
n false == 'false' // falsen false == '0' // truen " \t \r \n \t " == 0 // true
n 0 === '' // falsen 0 === '0' // false n '' === '0' // false n false === 'false' // falsen false === '0' // falsen " \t \r \n \t " === 0 // false
false:n falsen 0 (zero)n '' or “”n nulln undefinedn NaN (napr. 1/0)Všetko ostatné je true:n '0’n 'false’n [] (an empty array)n {} (an empty object)n function(){} (an “empty” f)
Vždy === miesto ==
https://dorey.github.io/JavaScript-Equality-Table/
Viacriadkové reťazce(indentácia je dôležitá)
Po Fortrane, ktorý zrušil medzery, lebo zaberali drahocenné miesto v 80-stĺpcovom riadku, prišiel Algol/Pascal/C/C+/Java, ktorý ignoroval layoutprogramu. Akýkoľvek počet medzier bol ekvivalentný jednej a konce riadkovsa ignorovali (resp. stáli za medzeru). A každý preferoval iný formát. Viacforemnosť zabíja. Vznikla potreba formátovať programy.Prišiel Python, ktorý za cenu ušetrenia blokových zátvoriek predpísallayout/indentáciu programu.Ale to nie je všetko, prečo je druhý program (JS) zlý ?
var long_line_1 = "This is a \long line"; // ok
var long_line_2 = "This is a \long line"; // syntax error
Priradenie v testen let a = 5, b = 7
n if (a = b) { ... } // a je 7
čo je vlastne explicitne zapísané toto:n a = bn if (a) { ... }
avšak programátor možno myslel niečo inén if (a == b) { ... }n if (a === b) { ... }
Scope(deklarujte všetky premenné na začiatku funkcie)
n JavaScript prevzal syntax blokov z C/Java, ale ignoruje block-scope, t.j. že premenná deklarovaná v bloku nie je inde viditeľná
n ak deklarujete (a príp. inicializujete) premennú v strede funkcie, viditeľná je aj pred definíciou, ale nemá hodnotu...
function foo() {console.log(a); // je definovaná, ale má hodnotu undefinedvar a = 0;console.log(a); // 0
}
for(var i = 1; i <= 10; i++) { } // ...console.log(i); // 11 // ... takto to bolo v Basicu...
Používajte let lebo akceptuje block-scope !
Functional scopen JavaScript síce používa blokovú syntax, nerešpektuje block-scope, ale
pozná funkcie ako hodnoty, a rešpektuje functional-scope...
var x = 1, y = 2;function f() {
var y = 4, z = 6;// x = 1, y = 4, z = 6x += y+z;// x = 11, y = 4, z = 6
};// x = 1, y = 2, z = undefinedf();// x = 11, y = 2, z = undefined
with(pravdepodobne pochádza z Pascalu/Pythonu)
with (obj) {a = b;
}a znamená (???):n a = b;n a = obj.b;n obj.a = b;n obj.a = obj.b;
V skutočnosti znamená toto (takže všetky štyri možnosti):if (obj.a === undefined) {
a = obj.b === undefined ? b : obj.b;} else {
obj.a = obj.b === undefined ? b : obj.b;}
Dobrovoľné zátvorky blokuRovnaké v mnohých iných jazykochif (ok)
t = true;zmeníte na:if (ok)
t = true;foo( );
a myslíte tým toto:if (ok) {
t = true;foo( );
}ale v skutočnosti ste napísali toto:if (ok) {
t = true;}foo( );
Security update for iOS/OSXOriginány Apple kód na verifikovanie certifikatu (2014, update iOS 7.0.6):Vidíte chybu v tomto kóde ? … nevadí, ani Apple ju nenašiel...
if ((err = SSLFreeBuffer(hashCtx)) != 0)fail();
if ((err = ReadyHash(SSLHashSHA1, hashCtx)) != 0)fail();
if ((err = SSLHashSHA1.update(hashCtx, clientRandom)) != 0)fail();
if ((err = SSLHashSHA1.update(hashCtx, serverRandom)) != 0)fail();
if ((err = SSLHashSHA1.update(hashCtx, signedParams)) != 0)fail();fail();
if ((err = SSLHashSHA1.final(hashCtx, hashOut)) != 0)fail();
http://www.tidev.io/2014/03/04/how-you-can-learn-from-apples-mistake/
Vsúvanie bodkočiarky
function goo() {...return {errorCode : 0
};}
function goo() {...return {errorCode : 0
};}
;
JS za príkazom vyžaduje bodkočiarkuale svojou benevoletnosťou ju dovolí programátorovi nepísať a dopĺňa ju zaňAký je rozdiel, výsledok oboch kódov ?
Globálne premennén sú zlé, najmä ak projekt presiahne rozumnú veľkosť
n deklarácia globálnej premennej var foo = 5
n cez globálny objektwindow.foo = 5
n implicitná deklaráciafoo = 5
n Našťastie JS ES 6 prichádza s modulmi
Moduly(export, import)
// util.jsexport function add(a, b) {
return a + b;}export function mult(a, b) {
return a * b;}export var grav = 9.81;export { add, mult, grav };export *;
// import.jsimport {add, mult} from 'util.js';import * from './util.js';console.log(add(4,5));console.log(mult(4,5));
Defalutné argumentyfunction fib(n, a = 0, b = 1)
{if (n == 0) {return a;
} else {return fib(n-1, b, a+b);
} }console.log(fib(10));
"use strict";function fib(n) {var a = arguments.length > 1 &&
arguments[1] !== undefined ? arguments[1] : 0;
var b = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 1;
...
JavaScript: The Good Parts(Douglas Crockford)
A good programming language should teach you.
It took a generation to agree that:n high level languages were a good idea,n goto statement was a bad idea,n objects were a good idea,n lambdas (functions) were a good idea.
GOTO story
Edsger Dijkstra (1968). "Go To Statement Considered Harmful", Communications of the ACMFrank Rubin (1987). ""GOTO Considered Harmful" Considered Harmful“ , Communications of the ACMDonald Moore; ...(1987). "" 'GOTO Considered Harmful' Considered Harmful" Considered Harmful?„Dijkstra, Edsger On a Somewhat Disappointing Correspondence (EWD-1009)
clojureClojure objavil Abelson a Sussman, Sussmanv jazyku Scheme, MIT Lisp.
Potrebujete vnorené funkcie...
Clojure je ak premenná vnútornej funkcie odkazuje na premennú vonkajšej funkcie.
Zaujímavý je prípad, ak vonkajšia funkcia vráti potom ako hodnotu vnútornú funkciu, vonkajšia tým zanikne. Výsledná hodnota (vnútorná funkcia) ukazujena premennú zaniknuvšej vonkajšej funkcie.
Takmer 20 rokov si ho nikto nevšimol.Efektívna implementácia na stack-based architektúre nebola evidentná.Objavil sa v Haskelli.
clojurefunction clojure_fun() {
var state = 0; // premenná vonkajšej funkciereturn {
inc : function(delta) { state += delta },clr : function() { state = 0 },get : function() { return state },set : function(val ) { state = val } };
};var clo = clojure_fun();clo je { inc: [Function], clr: [Function], get: [Function], set: [Function] }var get = clo.get, set = clo.set, inc = clo.inc;clo.get() // 0clo.set(11); set(11);clo.get() // 11clo.inc(4); inc(4);clo.get() get() // 19
clojurefunction clojure_fun() {
var state = 0;return {
inc : function(delta) { state += delta },clr : function() { state = 0 },get : function() { return state },set : function(val ) { state = val } };
};Čo je clojure: funkcia (clojure-fun) vráti ako hodnotu funkciu, resp.viacero fcií, ktorá vidí lokálne premenné práve zaniknuvšej funkcie (state).
Lokálna premenná (state) preto nemôže zaniknúť návratom z funkcie (clojure-fun).
Stack-frame architektúra preto nemôže byť použitá, ale state musí na heap.
Generatory.py a clojures.js(Fibonacci)
JavaScript(clojure):function fibonacci() {let x = 0, y = 1;return function() {let tmp = x; x = y;y = tmp + y;return tmp;
}}g = fibonacci();for (var i = 0; i<20; i++) {console.log('fib(' + i + ')='+ g());
}
Python:def fibonacci():
x, y = 0, 1while True:
yield xx, y = y, x + y
g = fibonacci()for _ in range(20):
print(next(g))
// toto sa zacykli, for f in fibonacci():
print(f)
fib(0)=0 fib(1)=1 fib(2)=1 fib(3)=2 fib(4)=3 fib(5)=5 fib(6)=8 fib(7)=13 fib(8)=21 fib(9)=34 fib(10)=55
Generatory (.js vs. .py)(Fibonacci)
fibonaccy = {[Symbol.iterator]: function*() {var x = 0, y = 1;for (;;) {var tmp = x;x = y;y += tmp;yield y;
}}
}
for (var n of fibonaccy) {if (n > 1000)break;
console.log(n);}
Python:def fibonacci():
x, y = 0, 1while True:
yield xx, y = y, x + y
g = fibonacci()for _ in range(20):
print(next(g))
// toto sa zacykli, for f in fibonacci():
print(f)
1235813213455
Generatory a clojures(Eratostenove prvočísla)
Python:def integers(n):
while True:yield nn += 1
def sieve(d, sieved):for x in sieved:
if (x % d != 0):yield x
JavaScript:function integers(n) {return function() {
n ++;return n-1;
}};function sieve(d, sieved) {return function() {while(true) {x = sieved();if (x % d != 0)return x;
} }}
Generatory a clojures(Eratostenove prvočísla – pokračovanie)
Python:def integers(n): ...def sieve(d, sieved):...
def eratosten(ints):while True:
first = next(ints)yield firstints = sieve(first,
ints)def take(n,g):
for i in range(n):yield next(g)
print(list(take(100,eratosten(integers(2)))))
JavaScript:function integers(n) ...function sieve(d, sieved) ...
function eratosten(ints) {return function() {
var first = ints();ints = sieve(first, ints);return first;
}}era = eratosten(integers(2));for (var i = 0; i<20; i++) {console.log('prime('+i+')='+
era());}
prime(0)=2 prime(1)=3 prime(2)=5 prime(3)=7 prime(4)=11 prime(5)=13 prime(6)=17 prime(7)=19 prime(8)=23 prime(9)=29
Tail recursion optimisationn bežné vo funkcionálnych jazykoch, Lisp, Scheme, Haskell, Scala n ale nie Clojure, v JS len od ES6
Iterácia:function add1(a, b) {if (a == 0) {return b;
} else {return add1(a - 1, b + 1);
}}add1(10000, 10000)20000add1(20000, 20000)40000add1(30000, 30000)too much recursion
Rekurzia:function add(a, b) {if (a == 0) {return b;
} else {return add(a - 1, b) + 1;
}}add(6000, 6000)12000add(10000, 10000)too much recursion
TRO znamená, že kompilátor/intepreterzbadá, že je to cyklus
Tail recursion optimisationn bežné vo funkcionálnych jazykoch, Lisp, Scheme, Haskell, Scala n ale nie Clojure, v JS len od ES6
Iterácia:function add1(a, b) {if (a == 0) {return b;
} else {return add1(a - 1, b + 1);
}}add1(10000, 10000)20000add1(20000, 20000)40000add1(30000, 30000)too much recursion
Takto sa to intepretuje:function add(a, b) {label:if (a == 0) {return b;
} else {a = a – 1b = b + 1goto label;
}}
TRO znamená, že kompilátor/intepreterzbadá, že je to cyklus
Tail recursion optimisation(ako písať iteratívne programy)
n akumulátorfunction fib(n, acc = 0, prev = 1) {if (n <= 1) {return acc;
} else {return fib(n-1, prev+acc, acc);
}}fib(500)8.616829160023833e+103
function factorial(n) {function fact(n, acc) {if (n < 2) {return acc;
} else {return fact(n-1, n*acc);
}}return fact(n, 1);
}factorial(100)9.332621544394418e+157
Tail recursion optimisation(vieme to vždy)
n Vieme každú rekurzívnu funkciu prepísať na cyklus (pomocou TRO) ?
Trampolinafunction odd1(n) {
returnn===0 ? false : even1(n-1);
}function even1(n) {
returnn===0 ? true : odd1(n-1);
}
function odd2(n) { return() => n===0 ?false:even2(n-1);
}function even2(n) {
return() => n===0 ? true:odd2(n-1);
}function trampolina(fn) {while ( // kým je funkcia
typeof fn === 'function') {fn = fn(); // aplikuj
} // ak už nie, je to výsledokreturn fn;
}
odd1(100)falseodd1(1001)trueodd1(10010)falseodd1(100100)too much recursion
trampolina(odd2(100))falsetrampolina(odd2(1001))truetrampolina(odd2(10010))falsetrampolina(odd2(100100))falsetrampolina(odd2(100100000))falsetrampolina(odd2(1001000001))true
Trampolinafunction factorial1(n, acc=1) {return (n < 2) ? acc :
factorial1(n-1, n*acc);}function sum1(n, acc=0) {return (n === 0) ? acc :
sum1(n-1, n+acc);}
function factorial2 (n, acc=1) {return () =>
(n < 2) ? acc : factorial2(n-1, n*acc);
}function sum2(n, acc=0) {return () =>
(n === 0) ? acc : sum2(n-1, n+acc);
}factorial1(10)3628800factorial1(100)9.332621544394418e+157factorial1(1000)Infinityfactorial1(10000)Infinityfactorial1(100000)too much recursion
trampolina(factorial2(100))3628800trampolina(factorial2(100))9.332621544394418e+157trampolina(factorial2(1000))Infinitytrampolina(factorial2(10000))Infinity...trampolina(factorial2(10000000))Infinity
Trampolinafunction factorial1(n, acc=1) {return (n < 2) ? acc :
factorial1(n-1, n*acc);}function sum1(n, acc=0) {return (n === 0) ? acc :
sum1(n-1, n+acc);}
function factorial2 (n, acc=1) {return () =>
(n < 2) ? acc : factorial2(n-1, n*acc);
}function sum2(n, acc=0) {return () =>
(n === 0) ? acc : sum2(n-1, n+acc);
}factorial1(10)3628800factorial1(100)9.332621544394418e+157factorial1(1000)Infinityfactorial1(10000)Infinityfactorial1(100000)too much recursion
trampolina(factorial2(100))3628800trampolina(factorial2(100))9.332621544394418e+157trampolina(factorial2(1000))Infinitytrampolina(factorial2(10000))Infinity...trampolina(factorial2(10000000))Infinity
sum1(100)5050sum1(10000)too much recursion
trampolina(sum2(10000000))50000005000000trampolina(sum2(100000000))5000000050000000
Continuation Passing Styleconsole.log(pythagoras(3, 4));function pythagoras(x, y) {
return x*x + y*y;}
console.log(pythagoras(3, 4));function pythagoras(x, y) {
return add(square(x), square(y));
}function square(x) {
return multiply(x, x);}function multiply(x, y) {
return x * y;}function add(x, y) {
return x + y;}https://stackoverflow.com/questions/14019341/whats-the-difference-between-a-continuation-and-a-callback
Continuation Passing Stylepythagoras(3, 4, console.log);function pythagoras(x, y, cont) {
square(x, function (x_squared) {square(y, function (y_squared) {
add(x_squared,y_squared, cont);});
});}function square(x, cont) {
multiply(x, x, cont); }
function multiply(x, y, cont) {cont(x * y); }
function add(x, y, cont) {cont(x + y); }
console.log(pythagoras(3,4));function pythagoras(x, y) {
return add(square(x), square(y));
}function square(x) {
return multiply(x, x);}function multiply(x, y) {
return x * y;}function add(x, y) {
return x + y;}
https://stackoverflow.com/questions/14019341/whats-the-difference-between-a-continuation-and-a-callback
Continuation Passing Stylepythagoras(3, 4, console.log);function pythagoras(x, y, cont) {
square(x, function (x_squared) {square(y, function (y_squared) {
add(x_squared,y_squared, cont);});
});}function square(x, cont) {
multiply(x, x, cont); }
function multiply(x, y, cont) {cont(x * y); }
function add(x, y, cont) {cont(x + y); }
pythagoras(3, 4, console.log);
function pythagoras(x, y, cont) {square(x, (x_squared) => {square(y, (y_squared) => {add(x_squared, y_squared, cont);
});});
}
https://stackoverflow.com/questions/14019341/whats-the-difference-between-a-continuation-and-a-callback
Continuation Passing Stylepythagoras(3, 4, console.log);function pythagoras(x, y, cont) {
var x_squared = callcc(square.bind(null, x));var y_squared = callcc(square.bind(null, y));add(x_squared, y_squared, cont);
}function callcc(f) {
var cc = function (x) {cc = x;
};f(cc);
return cc;}
https://stackoverflow.com/questions/14019341/whats-the-difference-between-a-continuation-and-a-callback
function square(x, cont) {multiply(x, x, cont);
}
function multiply(x, y, cont) {cont(x * y);
}
function add(x, y, cont) {cont(x + y);
}
Top Related