5
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

JavaScriptにもrangeが来るかもって話です

Posted at

注: 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にても提案されています。
そのため、上記の提案と仕様に違いがあるようです。

5
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?