【javascript】自己満足のrange関数

自己満足なので鼻で笑ってやってください。

#概要

逆順・小数点・引数検査を意識しつつ、それなりの速度を出せたら良いな。
という想いで組んでました。
他の人のコードと比較した訳ではありませんが、今の私にはこれが限界。

幾つかコードを載せますが、やってる事はほぼ同じです。

```javascript:
range(from, to, step);
```

|引数|変数名|既定値||
|:--:|:--:|:--:|:--|
|1|from|0|起点の数値|
|2|to|0|起点からこの数値に向かう|
|3|step|1|負の値は指定しない|

```javascript:出力結果
//空の配列を返すパターン
console.log( range() );				//引数が空
console.log( range(-5, false) );	//第3引数までに数値以外が指定
console.log( range(-5, 5, 0) );		//stepに0が指定

//from,toが同値
console.log( range(5, 5) );			//[5]

//引数が1つ => 0に向かってstep1で生成
console.log( range(-5.5) );			//[-5.5, -4.5, -3.5, -2.5, -1.5, -0.5]
console.log( range(5.5) );			//[0.5, 1.5, 2.5, 3.5, 4.5, 5.5]

//引数が２つ => step1
console.log( range(-5, 5) );		//[-5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5]
console.log( range(5, -5) );		//[5, 4, 3, 2, 1, 0, -1, -2, -3, -4, -5]

//引数が３つ => stepを指定
console.log( range(-5, 5, 2.5) );	//[-5, -2.5, 0, 2.5, 5]
console.log( range(5, -5, 2.5) );	//[5, 2.5, 0, -2.5, -5]

//４つ目以降の引数は影響なし
//負のstep値は絶対値で処理
console.log( range(-5, 5, -2, 2) );			//[-5, -3, -1, 1, 3, 5]
console.log( range(5, -5, 2, false, 2) );	//[5, 3, 1, -1, -3, -5]
```
#コード１
- 速度を意識したつもり
- `arguments`を使うためにアロー関数を使用しない

```javascript:
const range = function (from=0, to=0, step=1) {
	const array = new Array();
	
	//引数検査・調整
	const argLength = 2 in arguments ? 3 : arguments.length;
	for (let i = 0; i < argLength; i++) {
		if (Number.isFinite(arguments[i]) === false) return array;
	}
	switch (argLength) {
		case 0:
			return array;
		case 1:
			if (from > 0) {
				to = from;
				from = from - Math.floor(from);
			}
			break;
		case 3:
			if (step === 0) return array;
			step = Math.abs(step);
			break;
	}
	
	//本体
	if (from < to) {
		for (; from <= to; from += step) array.push(from);
	} else {
		for (; from >= to; from -= step) array.push(from);
	}
	return array;
};
```

#コード２
- 自由に書いたもの
- コード１より遅い

```javascript:
const range = (...args) => {	//arguments(from=0, to=0, step=1)
	//引数検査・調整
	args = args.slice(0, 3);
	if (!args.every(Number.isFinite)) return [];
	
	let [from=0, to=0, step=1] = args;
	const comp = [
		() => null,
		() => from > 0 ? (to = from, from = from - Math.floor(from)) : true,
		() => true,
		() => step ? step = Math.abs(step) : null
	];
	if ( comp[args.length]() === null ) return [];
	
	//本体
	const len = Math.abs(Math.ceil((from - to) / step)) + 1;
	if (from > to) step = -step;
	const calc = x => from + x * step;
	
	return [...Array(len).keys()].map(calc);
};
```

#コード３（ジェネレーター関数）
- コード１をジェネレーター関数に書き換えただけ


```javascript:
const range = function* (from=0, to=0, step=1) {
	//引数検査・調整
	const argLength = 2 in arguments ? 3 : arguments.length;
	for (let i = 0; i < argLength; i++) {
		if (Number.isFinite(arguments[i]) === false) return;
	}
	switch (argLength) {
		case 0:
			return;
		case 1:
			if (from > 0) {
				to = from;
				from = from - Math.floor(from);
			}
			break;
		case 3:
			if (step === 0) return;
			step = Math.abs(step);
			break;
	}
	
	//本体
	if (from < to) {
		for (; from <= to; from += step) yield from;
	} else {
		for (; from >= to; from -= step) yield from;
	}
};
```
#最後に
うーん、色々と長い。

[【javascript】一行で書かないrange関数 - Qiita](https://qiita.com/noenture/items/77fc9ea39e9afde3a801)
内容はこの記事の前に書いたコードなので見なくても問題ありません。