Updates for range proposal
July 2020 / Jack Works
What’s new since Stage 1
Options bag as 3rd parameter (PR)
// Initial design
Number.range(0, 5, 10)
// Now
Number.range(0, 5, 10)
Number.range(0, 5, { step: 10 })
// New inclusive option, 0, 1, 2, 3, 4, 5
[...Number.range(0, 5, { inclusive: true })]
New getters on %RangeIteratorPrototype% (PR)
const x = Number.range(0, 5, 10)
x.start // 0
x.end // 5
x.step // 10
x.inclusive // false
New runtime behaviors
// Allow BigInt range to Infinity
for (const x of BigInt.range(0n, Infinity))
if (x > 100n) break
// Allow step === 0, when start === end
Number.range(0, 0, 0) // Old: throw RangeError cause step is 0
//New: Emit nothing
// Infer step direction (1 or -1) when not specified
Number.range(0, 5).step === 1
Number.range(0, -5).step === -1
Number.range(0, -5, 1).step === 1
Semantics decisions
No need to change.
No need to change.
Current: Iterator.
Current: The latter.
Need Consensus: Iterator or Iterable(of something)
| Iterator | Iterable |
Consistency | with matchAll | with Array, Map, Set, ... |
Diffuseness (with Iter Helper) | ✅ range(...).map(...) | ❌ range(...).values().map(...) |
Closeness of Mapping | ✅ it should be iterator naturally | ❌ not very nature |
Error Proneness (Re-usable #17) | ❌ () => range(...) | ✅ range(...) |
Hard Mental Operations | ❌ Remember it’s not re-usable | ✅ Nothing |
Need Consensus: Plain function or Class?
| Plain function | Class |
Visibility / Diffuseness | ✅ Number.range(...) | ❌ new Number.Range(...) Maybe make it callable like Array? |
Consistency | ? | with all built-in Classes |
Closeness of Mapping | ❌ Behave like a class but construct like a normal function. (Note: has a prototype, methods on the prototype and brand check) | ✅ Behave like a class so let it become a class. |
Add test to the spec complaint polyfill
Add tests to make sure no regressions introduced.
The polyfill is implemented the spec step-by-step and updated with the spec for any editorial or normative change.
Therefore it can used to test if the spec is doing strange things.
// Not test262 style but Jest.js style
https://github.com/tc39/proposal-Number.range/blob/master/__tests__/test.js
Next step
Stage 2?
await.operations proposal
TL;DR; Extends the definition of AwaitExpression
await.all expr
// eq: await Promise.all(expr)
await.race expr
// eq: await Promise.race(expr)
await.allSettled expr
// eq: await Promise.allSettled(expr)
await.any expr
// eq: await Promise.any(expr)
Motivation & Usage
// before
await Promise.all(users.map(async x => fetchProfile(x.id)))
// after
await.all users.map(async x => fetchProfile(x.id))
Motivation: See discussion at Allow "awaiting" on arrays - 💡 Ideas
Possiblility to extend for await of syntax (#9)
(Not intent to add it in this proposal)
for await.all(const x of iterable) {
console.log(x)
}
// Loosely equals to: (despite break/continue/return/...)
await Promise.all([...iterable].map(async x => {
console.log(x)
})
Problems
await.all delegates;
try {
advance_stage(1);
} catch {}
Array.prototype.unique
July 2020 / Champion: Jack Works / Author: TechQuery
Motivation
Deduplication is one of the most common requirements in Data processing, especially in large Web Apps nowadays.
[...new Set(array)] in ECMAScript 6 isn't enough for Non-primitive values, and now, we may need a Array.prototype.unique().
API design
arr.unique()
// eq [...new Set(arr)] or …?
arr.unique("key")
arr.unique(1)
arr.unique(Symbol.for("key"))
// deduplicate by each_item[key]
arr.unique(x => x.toJSON())
// deduplicate by the provided function
Problems
Stage 1?