JavaScript Peter Borovanský, KAI, I-18, borovan(a)ii.fmph.uniba.sk

Slides:



Advertisements
Similar presentations
The JavaScript Programming Language
Advertisements

the javascript language BY SA.
Types in Ruby and other languages….  Classes and objects (vs prototypes)  Instance variables/encapsulation  Object creation  Object equality/comparison.
Semantic Analysis Chapter 6. Two Flavors  Static (done during compile time) –C –Ada  Dynamic (done during run time) –LISP –Smalltalk  Optimization.
Adapted from Scott, Chapter 6:: Control Flow Programming Language Pragmatics Michael L. Scott.
A Crash Course Python. Python? Isn’t that a snake? Yes, but it is also a...
ML: a quasi-functional language with strong typing Conventional syntax: - val x = 5; (*user input *) val x = 5: int (*system response*) - fun len lis =
Today Programming Style and Your Brain And Then There Was JavaScript Function the Ultimate The Metamorphosis of Ajax ES5: The New Parts.
Procedures and Control Flow CS351 – Programming Paradigms.
I just met you, and 'this' is crazy, but here's my NaN, so call(me) maybe? JavaScript is so weird.
Nov 10, Fall 2006IAT 8001 Debugging. Nov 10, Fall 2006IAT 8002 How do I know my program is broken?  Compiler Errors –easy to fix!  Runtime Exceptions.
1 Advanced Material The following slides contain advanced material and are optional.
Kevin Reuter & Brian Guthrie.  Multi-paradigm  Prototype based objects  Dynamic, weak typing.
Taking JavaScript Seriously IS NOT THE WORST IDEA.
Languages and tools. BY SA machine code.
1-Sep-15 Scala Apologia. 2 Java What’s wrong with Java? Not designed for highly concurrent programs The original Thread model was just wrong (it’s been.
1 JavaScript. 2 What’s wrong with JavaScript? A very powerful language, yet –Often hated –Browser inconsistencies –Misunderstood –Developers find it painful.
Functional Programming in Scheme and Lisp. Overview In a functional programming language, functions are first class objects. You can create them, put.
10/16/2015IT 3271 All about binding n Variables are bound (dynamically) to values n values must be stored somewhere in the memory. Memory Locations for.
Functional Programming and Lisp. Overview In a functional programming language, functions are first class objects. In a functional programming language,
C Derived Languages C is the base upon which many build C++ conventions also influence others *SmallTalk is where most OOP comes Java and Javascript have.
Hello.java Program Output 1 public class Hello { 2 public static void main( String [] args ) 3 { 4 System.out.println( “Hello!" ); 5 } // end method main.
USING UNITY JAVASCRIPT. CONVENTIONS AND SYNTAX IN JAVASCRIPT Case Sensitivity All keywords like var or function must be in lowercase. All variable names,
Milos Hauskrecht (PDF) Hieu D. Vu (PPT) LISP PROGARMMING LANGUAGE.
Introduction to Web Frontend Development with JavaScript.
6-Feb-16 Scala Apologia. 2 Java What’s wrong with Java? Not designed for highly concurrent programs The original Thread model was just wrong (it’s been.
CSE 130 : Winter 2009 Programming Languages Lecture 11: What’s in a Name ?
13-Jun-16 Scala Apologia. 2 Java What’s wrong with Java? Not designed for highly concurrent programs The original Thread model was just wrong (it’s been.
Introduction to Functional Programming Part 1 – The Basic Concepts Winter Young
Heath Carroll Bill Hanczaryk Rich Porter.  A Theory of Type Polymorphism in Programming ◦ Robin Milner (1977)  Milner credited with introducing the.
Chair of Software Engineering Void safety these slides contain advanced material and are optional.
CS314 – Section 5 Recitation 9
CSCI206 - Computer Organization & Programming
Object Lifetime and Pointers
CS314 – Section 5 Recitation 10
JavaScript Introduction
Chapter 10 Programming Fundamentals with JavaScript
Lecture 2 D&D Chapter 2 & Intro to Eclipse IDE Date.
dr Robert Kowalczyk WMiI UŁ
Working with Java.
CSE 374 Programming Concepts & Tools
ML: a quasi-functional language with strong typing
Introduction to Python
Lecture 4: Type Systems.
Programming Introduction to C++.
CSE 341 Lecture 5 efficiency issues; tail recursion; print
More on Recursive Methods
Variables and Arithmetic Operators in JavaScript
Functional Programming
Tutorial Lecture for EE562 Artificial Intelligence for Engineers
CSCI206 - Computer Organization & Programming
Programmazione I a.a. 2017/2018.
Sme produkty, musíme sa predať
Chap. 6 :: Control Flow Michael L. Scott.
Type system of Go/C# Seminar
Chapter 10 Programming Fundamentals with JavaScript
Integritné obmedzenia v SQL
Functional Programming
Control Flow.
Smelý Palko v Ohiu alebo pán Turing ide voliť
Chap. 6 :: Control Flow Michael L. Scott.
Scala Apologia 1-Jan-19.
CS5220 Advanced Topics in Web Programming JavaScript Basics
University of Kurdistan
JavaScript Reserved Words
Homework Any Questions?.
CISC124 Labs start this week in JEFF 155. Fall 2018
By Hector M Lugo-Cordero September 3, 2008
CIS 110: Introduction to Computer Programming
CS3220 Web and Internet Programming JavaScript Basics
Presentation transcript:

JavaScript Peter 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

Obsah Statické a dynamické typovanie, rôzne odtiene (1./3) Good & bad parts of Javascript (ES6) (2./3) scope clojure python generator pomocou clojures tail recursion optimisation, tail calls (3./3) trampolina continuation Passing Style vs. callback

JS Či chcete, alebo nie, Javascript je assembler internetu, 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, JS chýbajú typy, môžete v ňom začať písať aj bez príručky, je natoľko intuitívny, a o to viac zradný (najmä pre C++/Java programátora), môžete ho milovať alebo nenávidieť, nič medzi 

JS má špecifikáciu (ES6) 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%2Fwww.ecma-international.org%2Fecma-262%2F6.0%2FECMA-262.pdf&usg=AFQjCNFEsVjN8dQNWBifb3PDteslwvD9vA

Learn ES2015 (ES 6 features based on Hoban's es6features repo) 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 a better 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: high level languages were a good idea, goto statement was a bad idea, objects were a good idea, lambdas (functions) were a good idea.

Ako to začalo (dnes je to JavaScript ES6) interactive language for Netscape LiveScript: 10 dní na prototyp vychádzajúci z: Java - syntax, aj kus názvu jazyka Scheme/Lisp – lambdas – funkcie a functionálny pohľad, Self/Smalltalk – Smalltalk bez tried. 1995, zároveň sa úspešne rozvíja Goslingova Java Silná spoločná motivácia pre JS a Java: byť nezávislý od platformy Microsoft ten si vyvýja Jscript(Active Script), J++ Súboj Java Appletov a JavaScript vyhráva JS na plnej čiare Na úvodné programovanie v JS nepotrebujete čítať žiadnu obsiahlu dokumentáciu Stačí si otvoriť konzolu od browsera (alebo repl.it) a “programujete” Brendan Eich

Statici vs. dynamici Existuje 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 hodnoty ktorá 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) kým C++ (Java) oplýva komplikovanosťou a ťažkopádnosťou často spôsobenou statickou 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 dynamické typovanie je ale smrť pre väčšie projekty -- osobný názor, s ktorým môžete nesúhlasiť... 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: efektívny (t.j. kompilovaný) jazyk vhodný pre veľké projekty s rýchlym kompilátorom 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

Typovanie Dynamicky typovaný jazyk – typ premennej môže byť zmenený kedykoľvek na iný, napr. reťazec, int, time, objekt, ... Staticky typovaný jazyk – typ premennej je raz pre vždy určený a nemenný napr. deklaráciou, alebo prvým výskytom (Explicitne/Implicitne) _____________________________________________________ Silne (strong) typovaný jazyk – striknte určuje operácie, ktoré môžete s typovanou premennou, nesmiete miešať typy, inak nastane výnimka Slabo (weakly) typovaný jazyk – možete robiť čokolvek s rôznymi typmi, miešať ich, nenastane výnimka Javascript  http://blogs.perl.org/users/ovid/2010/08/what-to-know-before-debating-type-systems.html

Slabé typovanie no typing - assembler 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 ? 749711097 = 249903699 * 3 74 97 110 97 = “Jana” 74 9711097 = GMT: Monday 4. October 1993 5:04:57 char z = 'A'; printf("%d, %c", z, z); 65, A http://coding.smashingmagazine.com/2013/04/18/introduction-to-programming-type-systems/

Silné statické typovanie strong static typing (Java) informácia o type je prístupná v čase behu, a VM teda môže kontrolovať typ ak chceme pretypovať objekt na iný typ, Java v čase behu realizuje kontrolu vý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ód public 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é typovanie 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é typovanie strong dynamic typing (JS, Python, Ruby) if (new Date().getMinutes() > 29): z = “aaa” else: z = 5 print z z = 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 typing 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... Duck typing 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 function person['getName'] = null; // person.getName is not a function person['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/

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.” “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.” http://coding.smashingmagazine.com/2013/04/18/introduction-to-programming-type-systems/

0.1 + 0.2 == 0.3 if (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)

Perfection is achieved, not when there is nothing more to add, but when there is nothing left to take away -- Antoine de Saint-Exupery Viacznačnosť zabíja Ambiguita je smrť !

ASCII: (viacznačnosť zabíja) TAB vs. SPACE ’ vs. ” alert('wow') alert("WOW") UPPERCASE vs. lowercase ( ↑ , ↓) case sensitivity vznikla s ASCII-7 https://www.youtube.com/watch?v=SsoOG6ZeyUI Richard Hendrix HBO Silicon Valley SE03

var vs. let function varTest() { var x = 1; if (true) { var x = 2; // rovnaká premenná, var ignoruje block-scope console.log(x); // 2 } console.log(x); // 2 – tvrdá rana pre programátora vyškoleného } v C, C++, Java, ... function letTest() { let x = 1; 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. let function 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) JS má dve hodnoty pre nedefinovanú hodnotu null a undefined typeof 12 'number' typeof 'wow' 'string' typeof null 'object' ??? typeof undefined 'undefined' NULL (okrem iných vecí ako QuickSort, CSP, ...) objavil/zaviedol Tony Hoare pre 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 system for references in an object oriented language (ALGOLW). My goal was to ensure that all use of references should be absolutely safe, with checking performed automatically by the compiler. But I couldn't resist the temptation to put in a 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) 0 == '' // true, platí aj opačne 0 == '0' // true, platí aj opačne '' == '0' // false false == 'false' // false false == '0' // true " \t \r \n \t " == 0 // true 0 === '' // false 0 === '0' // false '' === '0' // false false === 'false' // false false === '0' // false " \t \r \n \t " === 0 // false false: false 0 (zero) '' or “” null undefined NaN (napr. 1/0) Všetko ostatné je true: '0’ 'false’ [] (an empty array) {} (an empty object) 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 layout programu. Akýkoľvek počet medzier bol ekvivalentný jednej a konce riadkov sa 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ísal layout/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 teste let a = 5, b = 7 if (a = b) { ... } // a je 7 čo je vlastne explicitne zapísané toto: a = b if (a) { ... } avšak programátor možno myslel niečo iné if (a == b) { ... } if (a === b) { ... }

Scope (deklarujte všetky premenné na začiatku funkcie) JavaScript prevzal syntax blokov z C/Java, ale ignoruje block-scope, t.j. že premenná deklarovaná v bloku nie je inde viditeľ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 undefined var 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 scope 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 = 6 x += y+z; // x = 11, y = 4, z = 6 }; // x = 1, y = 2, z = undefined f(); // x = 11, y = 2, z = undefined

with (pravdepodobne pochádza z Pascalu/Pythonu) with (obj) { a = b; } a znamená (???): a = obj.b; obj.a = b; 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 bloku Rovnaké v mnohých iných jazykoch if (ok) t = true; zmeníte na: foo( ); a myslíte tým toto: if (ok) { } ale v skutočnosti ste napísali toto:

Security update for iOS/OSX Originá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) if ((err = SSLHashSHA1.update(hashCtx, clientRandom)) != 0) if ((err = SSLHashSHA1.update(hashCtx, serverRandom)) != 0) if ((err = SSLHashSHA1.update(hashCtx, signedParams)) != 0) if ((err = SSLHashSHA1.final(hashCtx, hashOut)) != 0) http://www.tidev.io/2014/03/04/how-you-can-learn-from-apples-mistake/

Vsúvanie bodkočiarky ... JS za príkazom vyžaduje bodkočiarku ale svojou benevoletnosťou ju dovolí programátorovi nepísať a dopĺňa ju zaň Aký je rozdiel, výsledok oboch kódov ? function goo() { ... return { errorCode : 0 }; } function goo() { ... return { errorCode : 0 }; } ;

Globálne premenné sú zlé, najmä ak projekt presiahne rozumnú veľkosť deklarácia globálnej premennej var foo = 5 cez globálny objekt window.foo = 5 implicitná deklarácia foo = 5 Našťastie JS ES 6 prichádza s modulmi

Moduly (export, import) // util.js export 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.js import {add, mult} from 'util.js'; import * from './util.js'; console.log(add(4,5)); console.log(mult(4,5));

Defalutné argumenty function 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: high level languages were a good idea, goto statement was a bad idea, objects were a good idea, lambdas (functions) were a good idea.

GOTO story Edsger Dijkstra (1968). "Go To Statement Considered Harmful", Communications of the ACM Frank Rubin (1987). ""GOTO Considered Harmful" Considered Harmful“ , Communications of the ACM Donald Moore; ...(1987). "" 'GOTO Considered Harmful' Considered Harmful" Considered Harmful?„ Dijkstra, Edsger On a Somewhat Disappointing Correspondence (EWD-1009)

clojure Clojure objavil Abelson a Sussman, Sussman v 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) ukazuje na 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.

clojure function clojure_fun() { var state = 0; // premenná vonkajšej funkcie return { 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() // 0 clo.set(11); set(11); clo.get() // 11 clo.inc(4); inc(4); clo.get() get() // 19

clojure function 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()); 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 Python: def fibonacci(): x, y = 0, 1 while True: yield x x, y = y, x + y g = fibonacci() for _ in range(20): print(next(g)) // toto sa zacykli, for f in fibonacci(): print(f)

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); 1 2 3 5 8 13 21 34 55 Python: def fibonacci(): x, y = 0, 1 while True: yield x x, y = y, x + y g = fibonacci() for _ in range(20): print(next(g)) // toto sa zacykli, for f in fibonacci(): print(f)

Generatory a clojures (Eratostenove prvočísla) JavaScript: function integers(n) { return function() { n ++; return n-1; } }; function sieve(d, sieved) { while(true) { x = sieved(); if (x % d != 0) return x; } } Python: def integers(n): while True: yield n n += 1 def sieve(d, sieved): for x in sieved: if (x % d != 0): yield x

Generatory a clojures (Eratostenove prvočísla – pokračovanie) 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 Python: def integers(n): ... def sieve(d, sieved):... def eratosten(ints): while True: first = next(ints) yield first ints = sieve(first, ints) def take(n,g): for i in range(n): yield next(g) print(list(take(100, eratosten(integers(2)))))

Tail recursion optimisation bežné vo funkcionálnych jazykoch, Lisp, Scheme, Haskell, Scala ale nie Clojure, v JS len od ES6 Rekurzia: function add(a, b) { if (a == 0) { return b; } else { return add(a - 1, b) + 1; } add(6000, 6000) 12000 add(10000, 10000) too much recursion Iterácia: function add1(a, b) { if (a == 0) { return b; } else { return add1(a - 1, b + 1); } add1(10000, 10000) 20000 add1(20000, 20000) 40000 add1(30000, 30000) too much recursion TRO znamená, že kompilátor/intepreter zbadá, že je to cyklus

Tail recursion optimisation bežné vo funkcionálnych jazykoch, Lisp, Scheme, Haskell, Scala ale nie Clojure, v JS len od ES6 Takto sa to intepretuje: function add(a, b) { label: if (a == 0) { return b; } else { a = a – 1 b = b + 1 goto label; } Iterácia: function add1(a, b) { if (a == 0) { return b; } else { return add1(a - 1, b + 1); } add1(10000, 10000) 20000 add1(20000, 20000) 40000 add1(30000, 30000) too much recursion TRO znamená, že kompilátor/intepreter zbadá, že je to cyklus

Tail recursion optimisation (ako písať iteratívne programy) akumulátor function 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) Vieme každú rekurzívnu funkciu prepísať na cyklus (pomocou TRO) ?

Trampolina function odd1(n) { return n===0 ? false : even1(n-1); } function even1(n) { n===0 ? true : odd1(n-1); function odd2(n) { return () => n===0 ?false:even2(n-1); } function even2(n) { () => 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ýsledok return fn; trampolina(odd2(100)) false trampolina(odd2(1001)) true trampolina(odd2(10010)) trampolina(odd2(100100)) trampolina(odd2(100100000)) trampolina(odd2(1001000001)) odd1(100) false odd1(1001) true odd1(10010) odd1(100100) too much recursion

Trampolina function 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) { (n === 0) ? acc : sum2(n-1, n+acc); factorial1(10) 3628800 factorial1(100) 9.332621544394418e+157 factorial1(1000) Infinity factorial1(10000) factorial1(100000) too much recursion trampolina(factorial2(100)) 3628800 9.332621544394418e+157 trampolina(factorial2(1000)) Infinity trampolina(factorial2(10000)) ... trampolina(factorial2(10000000))

Trampolina function 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) { (n === 0) ? acc : sum2(n-1, n+acc); sum1(100) 5050 sum1(10000) too much recursion factorial1(10) 3628800 factorial1(100) 9.332621544394418e+157 factorial1(1000) Infinity factorial1(10000) factorial1(100000) too much recursion trampolina(factorial2(100)) 3628800 9.332621544394418e+157 trampolina(factorial2(1000)) Infinity trampolina(factorial2(10000)) ... trampolina(factorial2(10000000)) trampolina(sum2(10000000)) 50000005000000 trampolina(sum2(100000000)) 5000000050000000

Continuation Passing Style console.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 Style pythagoras(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 Style pythagoras(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 Style pythagoras(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; function square(x, cont) { multiply(x, x, cont); } function multiply(x, y, cont) { cont(x * y); function add(x, y, cont) { cont(x + y); https://stackoverflow.com/questions/14019341/whats-the-difference-between-a-continuation-and-a-callback