Slide 1

Slide 1 text

3/11/2019 future-js.md http://localhost:63578/future-js.html?print-pdf#/ 1/46 Future JavaScript: Future JavaScript: what is still missing? what is still missing? JS Kongress, Munich, 2019-03-11 JS Kongress, Munich, 2019-03-11

Slide 2

Slide 2 text

3/11/2019 future-js.md http://localhost:63578/future-js.html?print-pdf#/ 2/46 What is this talk about? What is this talk about? JavaScript has grown considerably in recent years, starting with ES6/ES2015. Already quite well rounded: modules, async (incl. async iteration), etc. What features are still missing? Details: My opinion Most important features only Others may also be useful (risk: bloat) (Mostly) based on officially proposed features

Slide 3

Slide 3 text

3/11/2019 future-js.md http://localhost:63578/future-js.html?print-pdf#/ 3/46 Background: How is Background: How is JavaScript designed? JavaScript designed?

Slide 4

Slide 4 text

3/11/2019 future-js.md http://localhost:63578/future-js.html?print-pdf#/ 4/46 TC39 process TC39 process TC39 (Ecma Technical Committee 39): evolves JavaScript Process is agile: focus is on features, not on ECMAScript releases. Feature proposals go through stages from 0 (strawman) to 4 (finished). Yearly releases of ECMAScript versions (starting with ES2016) Comprise whatever features are finished

Slide 5

Slide 5 text

3/11/2019 future-js.md http://localhost:63578/future-js.html?print-pdf#/ 5/46 TC39 process: stages TC39 process: stages Stage 0: strawman Stage 1: proposal Stage 2: draft Stage 3: candidate Stage 4: finished Pick champions First spec text, 2 implementations Spec complete Test 262 acceptance tests Review at TC39 meeting TC39 helps Likely to be standardized Done, needs feedback from implementations Ready for standardization Sketch

Slide 6

Slide 6 text

3/11/2019 future-js.md http://localhost:63578/future-js.html?print-pdf#/ 6/46 Future JS: Values Future JS: Values

Slide 7

Slide 7 text

3/11/2019 future-js.md http://localhost:63578/future-js.html?print-pdf#/ 7/46 Comparing objects by value (1/2) Comparing objects by value (1/2) Comparison by value: primitives. Comparison by identity: objects. > 'abc' === 'abc' true > {x: 1, y: 4} === {x: 1, y: 4} false > ['a', 'b'] === ['a', 'b'] false

Slide 8

Slide 8 text

3/11/2019 future-js.md http://localhost:63578/future-js.html?print-pdf#/ 8/46 Comparing by value (2/2) Comparing by value (2/2) Useful: comparing objects by value (“object value types”). Create a new kind of objects. How? Possibility: new object literals, new Array literals Possibility: new kind of class definition [Currently no proposal] > #{x: 1, y: 4} === #{x: 1, y: 4} true > #['a', 'b'] === #['a', 'b'] true @[ValueType] class Point { // ··· }

Slide 9

Slide 9 text

3/11/2019 future-js.md http://localhost:63578/future-js.html?print-pdf#/ 9/46 Putting objects into data structures Putting objects into data structures Solutions: Value types Customize key management via callbacks: Hash table: equality, hash code Sorted tree: comparing two keys const m = new Map(); m.set({x: 1, y: 4}, 1); m.set({x: 1, y: 4}, 2); assert.equal(m.size, 2);

Slide 10

Slide 10 text

3/11/2019 future-js.md http://localhost:63578/future-js.html?print-pdf#/ 10/46 Large integers (1/2) Large integers (1/2) Normal numbers only give you 53 bits (plus sign) for integers: > 2 ** 53 9007199254740992 > (2 ** 53) + 1 // can’t be represented 9007199254740992 > (2 ** 53) + 2 9007199254740994 > Number.MAX_SAFE_INTEGER 9007199254740991

Slide 11

Slide 11 text

3/11/2019 future-js.md http://localhost:63578/future-js.html?print-pdf#/ 11/46 Large integers (2/2) Large integers (2/2) BigInts grow as necessary: Fixed size (e.g. 64 bits): casting [ ] > 2n ** 53n 9007199254740992n > (2n ** 53n) + 1n 9007199254740993n const int64a = BigInt.asUintN(64, 12345n); const int64b = BigInt.asUintN(64, 67890n); const result = BigInt.asUintN(64, int64a * int64b); Stage 3 proposal

Slide 12

Slide 12 text

3/11/2019 future-js.md http://localhost:63578/future-js.html?print-pdf#/ 12/46 Decimal: base 10 oating point Decimal: base 10 oating point numbers (1/2) numbers (1/2) Normal numbers (base 2 floating point): Decimal values (base 10 floating point, stage 0): Important for: Scientific computing Financial technology (fintech) Etc. > 0.1 + 0.2 0.30000000000000004 > 0.1m + 0.2m 0.3m

Slide 13

Slide 13 text

3/11/2019 future-js.md http://localhost:63578/future-js.html?print-pdf#/ 13/46 Decimal: base 10 oating point Decimal: base 10 oating point numbers (2/2) numbers (2/2) Options: Rationals Fixed-size decimals BigDecimals [ ] Stage 0 proposal

Slide 14

Slide 14 text

3/11/2019 future-js.md http://localhost:63578/future-js.html?print-pdf#/ 14/46 Categorizing values Categorizing values Problems with the status quo: Must decide between typeof and instanceof typeof quirks: typeof null is 'object' typeof a function is 'function' (not 'object') instanceof does not work with objects from other realms (frames etc.) May be fixable via a library (WIP of mine).

Slide 15

Slide 15 text

3/11/2019 future-js.md http://localhost:63578/future-js.html?print-pdf#/ 15/46 Future JS: Functional Future JS: Functional programming programming

Slide 16

Slide 16 text

3/11/2019 future-js.md http://localhost:63578/future-js.html?print-pdf#/ 16/46 More expressions (1/3) More expressions (1/3) C-style languages distinguish: Expressions (“produce values”): Statements (“do something”): Only expressions can be arguments in function calls, etc. // Conditional expression const str1 = someBool ? 'yes' : 'no'; // Conditional statement let str2; if (someBool) { str2 = 'yes'; } else { str2 = 'no'; }

Slide 17

Slide 17 text

3/11/2019 future-js.md http://localhost:63578/future-js.html?print-pdf#/ 17/46 More expressions (2/3) More expressions (2/3) Proposal – do expressions: const str = do { if (someBool) { 'yes' } else { 'no' } };

Slide 18

Slide 18 text

3/11/2019 future-js.md http://localhost:63578/future-js.html?print-pdf#/ 18/46 More expressions (3/3) More expressions (3/3) do expression: [ ] const n = 3; const str = do { switch (n) { case 1: 'one'; break; case 2: 'two'; break; case 3: 'three'; break; } }; assert.equal(str, 'three'); Stage 1 proposal

Slide 19

Slide 19 text

3/11/2019 future-js.md http://localhost:63578/future-js.html?print-pdf#/ 19/46 Pattern matching: destructuring Pattern matching: destructuring switch switch Proposal at stage 1: [ ] const resource = await fetch(jsonService); case (resource) { when {status: 200, headers: {'Content-Length': s}} -> { console.log(`size is ${s}`); } when {status: 404} -> { console.log('JSON not found'); } when {status} if (status >= 400) -> { throw new RequestError(res); } } Stage 1 proposal

Slide 20

Slide 20 text

3/11/2019 future-js.md http://localhost:63578/future-js.html?print-pdf#/ 20/46 Pipeline operator Pipeline operator Two competing proposals. We look at Smart Pipelines. Consider: Pipeline operator (more intuitive): Equivalent: const y = h(g(f(x))); const y = x |> f |> g |> h; f(123) 123 |> f

Slide 21

Slide 21 text

3/11/2019 future-js.md http://localhost:63578/future-js.html?print-pdf#/ 21/46 Pipeline operator: partial application Pipeline operator: partial application Think .bind() – equivalent (marker #): Use functions as if they were methods: [ ] 123 |> f('a', #, 'b') 123 |> (x => f('a', x, 'b')) import {filter, map} from 'array-tools'; const result = arr |> filter(#, x => x >= 0) |> map(#, x => x * 2) ; Stage 1 proposal

Slide 22

Slide 22 text

3/11/2019 future-js.md http://localhost:63578/future-js.html?print-pdf#/ 22/46 Future JS: Concurrency Future JS: Concurrency

Slide 23

Slide 23 text

3/11/2019 future-js.md http://localhost:63578/future-js.html?print-pdf#/ 23/46 Concurrency Concurrency Current de-facto standard (browsers, Node.js): Worker API Disadvantage: heavyweight – each Worker has its own realm (with global variables etc.). More lightweight concurrency would be nice.

Slide 24

Slide 24 text

3/11/2019 future-js.md http://localhost:63578/future-js.html?print-pdf#/ 24/46 Future JS: Standard library Future JS: Standard library

Slide 25

Slide 25 text

3/11/2019 future-js.md http://localhost:63578/future-js.html?print-pdf#/ 25/46 Standard library: modules instead of Standard library: modules instead of namespace objects (1/3) namespace objects (1/3) Currently – pseudo-modules: Math.max() JSON.parse() Object.keys() Reflect.ownKeys()

Slide 26

Slide 26 text

3/11/2019 future-js.md http://localhost:63578/future-js.html?print-pdf#/ 26/46 Standard library: modules instead of Standard library: modules instead of namespace objects (2/3) namespace objects (2/3) Wish – standard library via build-in modules (custom protocol std:): // New: import {max} from 'std:math'; assert.equal( max(-1, 5), 5); // Old: assert.equal( Math.max(-1, 5), 5);

Slide 27

Slide 27 text

3/11/2019 future-js.md http://localhost:63578/future-js.html?print-pdf#/ 27/46 Standard library: modules instead of Standard library: modules instead of namespace objects (3/3) namespace objects (3/3) Benefits: JavaScript becomes more modular (note: also possible via “lazy” namespace objects): Possibly faster startup time Possibly reduced memory consumption Calling imported functions is faster than calling functions in properties : Explores first steps To be determined: exact functionality Stage 1 proposal

Slide 28

Slide 28 text

3/11/2019 future-js.md http://localhost:63578/future-js.html?print-pdf#/ 28/46 Standard library: helpers for iterables Standard library: helpers for iterables (sync and async) (1/3) (sync and async) (1/3) Currently: must convert iterables to Arrays. Better – operations that work with iterables (inspiration: Python’s itertools): const iterable = new Set([-1, 0, -2, 3]); const filteredArray = [...iterable].filter(x => x >= 0); assert.deepEqual(filteredArray, [0, 3]); const filteredIterable = filter(iterable, x => x >= 0); assert.deepEqual( // Only convert iterable to Array to check what’s in it [...filteredIterable], [0, 3]);

Slide 29

Slide 29 text

3/11/2019 future-js.md http://localhost:63578/future-js.html?print-pdf#/ 29/46 Standard library: helpers for iterables Standard library: helpers for iterables (sync and async) (2/3) (sync and async) (2/3) More examples: const iterable = new Set([-1, 0, -2, 3]); // Count elements in an iterable assert.equal(count(iterable), 4); // Create an iterable over a part of an existing iterable assert.deepEqual( [...slice(iterable, 2)], [-1, 0]);

Slide 30

Slide 30 text

3/11/2019 future-js.md http://localhost:63578/future-js.html?print-pdf#/ 30/46 Standard library: helpers for iterables Standard library: helpers for iterables (sync and async) (3/3) (sync and async) (3/3) More examples: [Currently no proposal] // Number the elements of an iterable for (const [i,x] of zip(range(0), iterable)) { console.log(i, x); } // Output: // 0, -1 // 1, 0 // 2, -2 // 3, 3

Slide 31

Slide 31 text

3/11/2019 future-js.md http://localhost:63578/future-js.html?print-pdf#/ 31/46 Standard library: immutable data Standard library: immutable data Support for non-destructively transforming data. Existing examples: : lightweight; works with normal objects & Arrays. : more powerful and heavyweight; has its own data structures. [Currently no proposal] Immer Immutable.js

Slide 32

Slide 32 text

3/11/2019 future-js.md http://localhost:63578/future-js.html?print-pdf#/ 32/46 Standard library: Better support for Standard library: Better support for date times date times Stage 2 proposal: – better date time API. temporal const dateTime = new CivilDateTime(2000, 12, 31, 23, 59); const instantInChicago = dateTime.withZone('America/Chicago');

Slide 33

Slide 33 text

3/11/2019 future-js.md http://localhost:63578/future-js.html?print-pdf#/ 33/46 Features that may not be Features that may not be needed needed

Slide 34

Slide 34 text

3/11/2019 future-js.md http://localhost:63578/future-js.html?print-pdf#/ 34/46 Optional chaining: pros and cons Optional chaining: pros and cons . Use case: Equivalent: Stage 1 proposal obj?.foo?.bar?.baz obj?.prop (obj === undefined || obj === null) ? undefined : obj.prop

Slide 35

Slide 35 text

3/11/2019 future-js.md http://localhost:63578/future-js.html?print-pdf#/ 35/46 Optional chaining: pros and cons Optional chaining: pros and cons Pro: concise Cons: Deep nesting should be avoided (harder to change) Tolerance can hide problems Alternatives: Helper functions that extract data Pre-process (clean up) input data before working with it

Slide 36

Slide 36 text

3/11/2019 future-js.md http://localhost:63578/future-js.html?print-pdf#/ 36/46 Really needed: operator overloading? Really needed: operator overloading? Infix function application may be enough: Benefits: Compared to operator overloading: Simple mechanism Not limited to built-in operators Compared to normal function application: Nested expressions remain readable: import {BigDecimal, plus} from 'big-decimal'; const bd1 = new BigDecimal('0.1'); const bd2 = new BigDecimal('0.2'); const bd3 = bd1 @plus bd2; // plus(bd1, bd2) a @ plus b @ minus c @ times d times(minus(plus(a, b), c), d)

Slide 37

Slide 37 text

3/11/2019 future-js.md http://localhost:63578/future-js.html?print-pdf#/ 37/46 Various smaller wishes Various smaller wishes

Slide 38

Slide 38 text

3/11/2019 future-js.md http://localhost:63578/future-js.html?print-pdf#/ 38/46 Chained exceptions Chained exceptions Indicate cause of a custom error new ChainedError(msg, origError)

Slide 39

Slide 39 text

3/11/2019 future-js.md http://localhost:63578/future-js.html?print-pdf#/ 39/46 Composable regular expressions Composable regular expressions const regex = re`/^${RE_YEAR}-${RE_MONTH}-${RE_DAY}$/u`;

Slide 40

Slide 40 text

3/11/2019 future-js.md http://localhost:63578/future-js.html?print-pdf#/ 40/46 Escaping text for regular expressions Escaping text for regular expressions Use case: replacing a plain text multiple times. > const re = new RegExp(RegExp.escape(':-)'), 'ug'); > ':-) :-) :-)'.replace(re, ' ') ' '

Slide 41

Slide 41 text

3/11/2019 future-js.md http://localhost:63578/future-js.html?print-pdf#/ 41/46 Array.prototype.get() Array.prototype.get() for for negative indices negative indices > ['a', 'b'].get(-1) 'b'

Slide 42

Slide 42 text

3/11/2019 future-js.md http://localhost:63578/future-js.html?print-pdf#/ 42/46 As-patterns for matching and As-patterns for matching and destructuring destructuring Proposal: function f(...[x, y] as args) { if (args.length !== 2) { throw new Error(); } // ··· }

Slide 43

Slide 43 text

3/11/2019 future-js.md http://localhost:63578/future-js.html?print-pdf#/ 43/46 Enums Enums Closing a gap with TypeScript: enum WeekendDay { Saturday, Sunday } const day = WeekendDay.Sunday;

Slide 44

Slide 44 text

3/11/2019 future-js.md http://localhost:63578/future-js.html?print-pdf#/ 44/46 Tagged collection literals Tagged collection literals Proposal withdrawn: const myMap = Map!{1: 2, three: 4, [[5]]: 6} // new Map([1,2], ['three',4], [[5],6]) const mySet = Set!['a', 'b', 'c']; // new Set(['a', 'b', 'c'])

Slide 45

Slide 45 text

3/11/2019 future-js.md http://localhost:63578/future-js.html?print-pdf#/ 45/46 Take-aways Take-aways Current JavaScript is already a fairly well-rounded language. Main wishes: Value types (object that are compared by value) BigInts, (Big)Decimals Pipeline operator Lightweight concurrency Bigger standard library

Slide 46

Slide 46 text

3/11/2019 future-js.md http://localhost:63578/future-js.html?print-pdf#/ 46/46 Further reading Further reading Blog post: My JS books (free online): Download slides: 2ality.com/2019/01/future-js.html exploringjs.com speakerdeck.com/rauschma/