読者です 読者をやめる 読者になる 読者になる

Panda Noir

JavaScript の限界を究めるブログです。

forもifも使わないプログラミング入門

JavaScript forもifも使わないプログラミング入門

入門記事を量産してる気がするけど気にしたら負け。

JavaScriptを動かす

言語は安定のJavaScriptです。まあ今回書く内容はRubyでもPythonでもPHPでもなんでもできます。たぶん。

環境構築?そんなものありません!安心してください。 次のリンクを開いてもらえばそれで準備完了です (怪しいうたい文句みたいですね)。

JSFiddle

開けましたか?そしたら、Hello worldしてみましょう。

以下のコードをコピーしてJAVASCRIPTと書いてある枠内に貼りつけ(ペースト)してください。

document.write('helo world');

左上のRUNを押して実行します。うまくいくと右下にhello worldと出ます。

以降、「コードを貼りつけてください」とあったらJAVASCRIPTの枠内に貼りつけることを意味します。

1と2を足してみよう

いよいよ本題に入ります。まず「1と2を足して表示」という課題です。簡単ですね。こうです。

document.write(1+2);

document.write()はそれで囲んだ中身を表示してくれます。今回でいえば1+2、つまり3を表示してくれます。

…え?これだけ?と思った人、大丈夫です。これから難易度が上がっていくので。むしろここでコケられると困ります。

補足

実はdocument.writeは使わない方がいいのですが、今回は一番面倒なことしないで済むので使っています。

1から10を足してみよう

さて、では1から10を足して表示してみてください。といっても難しいと思うので答えを書くと、

document.write(55);

こうです!

…冗談はさておき(これも立派な答えではありますが)、ちゃんと書くとこうなります。

document.write(1+2+3+4+5+6+7+8+9+10);

書くのしんどいです。でもこれくらいならまだ書けなくもないです。

1から2016まで足してみよう

ではここからが本題です。1から2016まで足してみましょう。100までなら5050!と即答できる人もいるでしょうが、2016までとなるとウっとなりますよね。

「数学使えばできるよ!」確かにその通りです。

document.write((1+2016)*(2016)/2);

でも誰がこれを見て「おっ1から2016まで足してるんだな」とわかりましょうか。いえ、誰もわかりません(反語)。少なくとも凡人の僕では無理です。

「じゃあfor使うしかないじゃん!」とお思いになるでしょう。

for(let i = 1, sum = 0; i <= 2016; i++) {
    sum += i;
}
document.write(sum);

でもこれが1から2016まで足してるとパッと見てわかりますか?僕にはわかりますが…と自慢するところではなくて。わかりませんよね普通。

そこで、こう書けばわかるのではないでしょうか?

document.write(range(1, 2016).reduce((a, b) => a + b, 0));

(このコードだけはコピペしてもうまく動きません。最後にちゃんと動くコードを用意してあるので試したい方はそちらをどうぞ)

解説

解説しましょう。range(1, 2016)は1から2016までの自然数の数列です。{1,2,3,...,2015,2016}ということです。

reduce((a, b) => a + b, 0) は実際の挙動を説明する方が早そうです。

まず、aに0が入ります。 reduce((a, b) => a + b, 0) の0です。そして、bには数列の先頭の1が入ります。そしたら、a+bが計算されます。答えは1です(0+1なので)。

そしたら、今度はこの計算結果がaに、数列で1の次の2がbになります。また計算すると今度は3となります。

そしてaは3(=1+2)に、bは3になり、aは6(=1+2+3)、bは4になり、aは10(=1+2+3+4)、bは5になりと順々に計算されていきます。

つまり

数列を頭から取り出していって総和を出しているわけです。いわば reduce((a, b) => a + b, 0) は数列の項をつなぐ演算子を提供しているわけです。

ということは、 range(1, 2016).reduce((a, b) => a + b, 0) って、 1から2016までの総和をそのままコードにしている 、と言えないでしょうか?

終わりに

実にキレイにコードにできました。forなんて使うのがバカバカしいですよね!

…まあfor使わないでコード書くのは不可能なのでそのうちやるにしても、初めはこういう風に「言葉のままコードにする」っていう方がいい気がします。

おまけ: ちゃんと動かせるコード

document.write(range(1, 2016).reduce((a, b) => a + b, 0));

function range(start, end) {
    var res = [];
    for (let i = start; i <= end; i++) {
        res.push(i);
    }
    return res;
}

…実はrangeとreduce使っていても内部的にはforを使っています(使わなくても書けないことはありませんが、JavaScriptは地獄なのでこれが一番安全です)。rangeとreduceという風にして隠ぺいしているだけなんですね。