注: Stage 1なので、この記事のとおり、実装される保証も、そもそも実装される保証もありません。提案されているってだけの話です。
というProposalでJavaScriptにNumber.rangeとBigInt.rangeを追加しようという提案がされています。
JavaScriptで連番の配列を作成する関数そのものは存在せず、間接的に生成するしかありません。
関数本来の使い方でないうえ、0からの連番でない場合は少し面倒です。
[...Array(5).keys()];//[0, 1, 2, 3, 4]
Array.from({ length: 4 }, (_, i) => i + 1);//[1, 2, 3, 4]
いろいろなライブラリにて、そのような関数は用意されています。
ですが、これを標準で用意しようというProposalです。
上記Proposalから引用します。
現状だと、Number、BigIntそれぞれに個別の関数が追加されいます。
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
上記の通り、配列でなくイテレーターを返します。
ですので、配列を生成する関数ではないようです。まぁ、 スプレッド構文を利用することで簡単に配列に変換できます。
また、Iterator HelpersのProposalを利用することで、filterやmapなでの関数も利用できます。
範囲ですが、fromを含み、toは含まないという範囲のようです。
[...Number.range(0,10)]//[0, 2, 3, 4, 5, 6, 7, 8, 9, 9]
[...Number.range(0,10,2)]//[0, 2, 4, 6, 8]
[...Number.range(0,11,2)]//[0, 4, 6, 8, 10]
無限イテレーター
この提案がイテレーターを返す利点として、無限イテレーターがあります。
for(const n of Number.range(0, Infinity)) {
if (n * n > 26) break;
console.log(n);
}
//0
//1
//2
//3
//4
//5
上記のコードのように、事前に列挙の終端が分からない場合に便利です。
詳細
interface NumberConstructor {
range(from: number, to: number, step?: number): Iterator<number>
// If accept Number.range(to)
range(to: number): Iterator<number>
}
interface BigIntConstructor {
range(from: BigInt, to: BigInt, step?: BigInt): Iterator<BigInt>
// If accept BigInt.range(to)
range(to: BigInt): Iterator<BigInt>
}
1番目の引数 from
列挙の開始の数字です。この数字は含まれます。
また、無限の値はエラーになります。
2番目に引数 to
列挙の数字の表示です。この数字は含まれません。
こちらは無限も許可されます。
1番目の引数>2番目の引数の場合でもstepが-1になることはなく、直後に終了するイテレーターになるようです。
また議論中のようですが、2番目以降の引数を省略した場合、1番目の引数が終端の数字となり、始点が0になるようです。
3番目の引数 step
1回ごとに加算される値です。省略した場合は1になります。
また、stepというプロパティをもつオブジェクトを渡した場合、そのstepプロパティの値が使われるようです。
また、無限の値もしくは0のときはエラーになります。
追加構文
関数だけでなく、構文でも連番が作れるようになるかもしれません。
[1..5];// [1,2,3,4,5]
[6..3];// [6,5,4,3]
[..4];// [0,1,2,3,4]
[2..];//[2,1,0]
[1..2..5];// [1,3,5]
[1..2..6];// [1,3,5]
[5..2..1];// [5,3,1]
[6..2..1];// [6,4,2]
[..2..5];// [0,2,4]
[..2..6];// [0,2,4,6]
[5..2..];// [5,3,1]
[6..2..];// [6,4,2,0]
多言語でよくある「..」で範囲をつくるやつですね。
こちらは始点、終点ともに含まれるようです。また、無限イテレーターは対応されていないようです。
また、始点、終点ともに省略した場合は0にあるようです。
始点>終点の場合は負の報告に列挙されるようです。
途中に数字を挟むことで、その数字が2番目の値になるような列挙がされるようです。
こちらは別のリポジトリで提案されており、上記のリポジトリのissueにても提案されています。
そのため、上記の提案と仕様に違いがあるようです。