1 of 10

Number.range & BigInt.range

March 2020

Jack Works

https://github.com/Jack-Works/proposal-Number.range

(Polyfill & Spec text available in the repo)

2 of 10

In other languages...

for x in 0..10 { // Rust

println!("{}", x);

}

for n in range(6): # Python

print(n)

foreach(var item in 1..100) // C#

{

Console.WriteLine(item);}

for (i in 1..4) print(i) // Kotlin

@for $i from 1 through $grid-columns { // SCSS

.grid-#{$i} {

@include grid-base($i);

@extend .grid-block;

}

}

: bat

FOR /L %%G IN (1,1,5) DO echo %%G

3 of 10

Today in JS

At least 20 different implementations in a single stackoverflow question

Tons of libraries providing a range: math.js, lodash, underscore.js, ramda, d3, range, fill-range, multi-integer-range, ……

;[...Array(5).keys()] // ES6

function range(size, startAt = 0) {

return [...Array(size).keys()].map(i => i + startAt)

}

_.range(1, 11) // lodash

Array.apply(null, Array(5)).map(function(_, i) {

return i // ES5 compatible

})

Array.from({ length: 20 }, (x, i) => i)

Array.from(new Array(20), (x, i) => i + lowerBound)

Array(10)

.fill(1)

.map((x, y) => x + y)

const range = (start, stop, step = 1) =>

Array(Math.ceil((stop - start) / step))

.fill(start)

.map((x, y) => x + y * step)

const RANGE = (a, b) =>

Array.from(

(function*(x, y) {

while (x <= y) yield x++

})(a, b)

)

4 of 10

Motivation

  • because we don’t have it yet

Without these functions, the language feels incomplete, and is a paper cut to what could be a very polished experience. Bringing this into the platform will improve performance of the web, and developer productivity as they no longer have to implement these common functions.

—— String.prototype.{padStart,padEnd}

5 of 10

Usage

for (const i of BigInt.range(0n, 43n)) console.log(i) // 0n to 42n

// With iterator helper proposal

Number.range(0, Infinity).take(1000).filter(x => !(x % 3)).toArray()

function* even() {

for (const i of Number.range(0, Infinity)) if (i % 2 === 0) yield i

}

[...Number.range(1, 100, 2)] // odd number from 1 to 99

6 of 10

Proposed API

interface NumberConstructor {

// Number.range(from, to, step?)

range(from: number, to: number, step?: number): Iterator<number>

}

interface BigIntConstructor {

// BigInt.range(from, to, step?)

range(from: bigint, to: bigint, step?: bigint): Iterator<bigint>

}

7 of 10

Goals

  • Arithmetic Sequence on Numbers
    • Incremental (0, 1, 2, 3, ...)
    • Decremental (0, -1, -2, -3, ...)
    • Step (0, 2, 4, 6, ...)
      • Non-integer step (Should we?) (0, 0.2, 0.4, ...)
  • Support BigInt (and future number types like Decimal)
    • Same as Arithmetic Sequence (if possible)
  • Infinite Sequence Number.range(0, Infinity) -> (0, 1, 2, 3, ...)

8 of 10

Non-goals

  • String Sequence ("a", "b", "c", "d", ...)
  • if (x in Number.range(0, 10)) return true
    • Kotlin have this feature

9 of 10

Wait for discussions (available at GitHub repo)

// What to do if the direction doesn't match? (GH #5)

// a. throw an Error | b. ignore the direction, infer from `from` and `to

// c. do nothing, cause a dead loop | d. yield nothing

Number.range(0, 10, -5)

Number.range(42, 100, 1e-323) // How to deal with this? This will cause a dead loop (GH #7)

BigInt.range(0, Infinity) // Infinite sequence for BigInt (GH #8)

oneToTen.includes(42) // Add some helper methods (GH#12)

Number.range(10) // Means [0, 10) (GH#18), [10, Infinity) (GH#14) or TypeError?

// Let it return an object with @@iterator instead of a raw iterator (GH#17)

10 of 10

Stage 1?