hack のためのネタ帳, etc,,,

状況

Google News のリコメンドに ってなものが流れてきたので、感想対象の を眺めてたんだけど、最初のところで

2.2. 命令型コード(JavaScript)
let sum = 0;
let x = 0;

for (let i = 0; i < 10; i++) {
  x = x + 1;
  console.log(x);
  sum = sum + x;
}

console.log(sum);
3.1. 関数型コード(JavaScript)
const add = (a, b) => a + b;
const sum = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10].reduce(add);
 
console.log(sum);

みたいな比較が出てきて、いや、確かに JavaScript で連番生成面倒ですよねと。
でも、命令形は連番生成してるのに関数型は手書き配列与えてるのはちょっとフェアじゃないのでは?と。

んで、「JavaScript 連番」とかでググるといろんなやり方が出て来て、
とりあえず、よくまとまっているのは、以下のスレッドだと思うのだけど、やっぱり地味に面倒だった。
最短は、... (spread syntax: スプレッド構文)keys() メソッド組み合わせて
[0:n) だと
[...Array(n).keys()]
[1:n] だと
[...Array(10)].map((v,i)=>1+i)
だろうか?
start, end, step, n, include_end 辺りの組み合わせで自由度求めると
let n = ((end - start + step - include_end ? 0 : 1) / step) | 0;
[...Array(n)].map((v,i)=>start + step * i)
みたいになりそう。
定形文として認識できればいいけれど、予備知識無しだと意図の分かりにくいコードなのは辛い。

余談

元ネタコードのレギュレーションを合わせてみる。

手書き配列の場合
命令形は
モダンな JS だと
let sum = 0;

for (const v of [1,2,3,4,5,6,7,8,9,10]) sum += v;

console.log(sum);
レガシーな JS だと
let sum = 0;
let a = [1,2,3,4,5,6,7,8,9,10]

for (let i in a) sum += a[i];

console.log(sum);
let sum = 0;
let a = [1,2,3,4,5,6,7,8,9,10]

for (let i = 0; i < length(a); i++) sum += a[i];

console.log(sum);
みたいな感じかな?

逆に連番生成で
関数型は
const add = (a, b) => a + b;
const sum = [...Array(10)].map((v,i)=>1 + i).reduce(add);
 
console.log(sum);
だろうか?

こういう話の脇道である連番生成が入ることで本質部分の対比がぼやけてしまうのは辛いところ。

その他、興味深い連番生成の方法

英語でググる場合は「javascript generate sequence」とかでよいのだろうか?

  • stackoverflow / 2010-09-20: How to generate sequence of numbers/chars in javascript? # comment-54335525
ジェネレーター関数使った range(start, end, step) の例がある。
function * range ( start, end, step ) {
  let state = start;
  while ( state < end ) {
    yield state;
    state += step;
  }
  return;
};

const generate_array = (start,end,step) => Array.from( range(start,end,step) );
const array = generate_array(1,10,2);
みたいな感じ。
関数使うなら中身はこれじゃなくても問題はないかなと言う気はする。

で紹介されてる Number.prototype[Symbol.iterator] に generator 仕込む例は強烈。
Number.prototype[Symbol.iterator] = function* () {
  for (let i=0; i < this; i++) {
    yield i;
  }
};
としておくことで、
for (x of 5) { console.log(x) }
[...5]
みたいな連番生成が可能になる。

コメントをかく


「http://」を含む投稿は禁止されています。

利用規約をご確認のうえご記入下さい

Wiki内検索

フリーエリア

管理人/副管理人のみ編集できます