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

nabeliwo note

5万人に1人になる。

arrow function素晴らしいなって話

JavaScript

技術力を伸ばしたい

ここ最近自分の技術力の無さと、エンジニアになってからの2年半の間に全然最大限の行動と努力ができていなかったことを実感している。
そんなわけでどうやって技術力をつけていこうかってのを考えながら生活している。

方向性としてはいくつかあると思っていて、

  • まったく新しいパラダイムの勉強をする
  • 別の言語の勉強をする
  • JavaScriptをさらに深くつきつめていく
  • 流行り廃りの関係の無いITの基礎を勉強する

っていう4つに分けられそう。

まったく新しいパラダイムの勉強をする

例えば関数型の考え方を勉強したり、今までやってきたプログラミングとは違うアプローチの実装の仕方を学ぶことで、開発のアプローチの幅を増やすという方法がある。

ちょうどよくこの本を持っているのでやってみようかなと思っている。

JavaScriptで学ぶ関数型プログラミング

JavaScriptで学ぶ関数型プログラミング

別の言語の勉強をする

これは、エンジニアとして複数の言語を扱えるのが当然であるという前提のもとに、その前提にとりあえず到達することを目指す感じ。
一応仕事でPHPを触っていた時期があるってのと、RubyScalaの基本構文だけは知っているという状況ではあるが、JavaScriptのように頭の中の設計をそのままコードにすらすらと落とし込むことは確実にできないし、現状一人の力でまともなものを作れる気がしない。

これも幅を広げるというジャンルに入る勉強方法だと思っている。が、現状優先度は低いと思っている。
挙げた4つの中では一番優先度を低く考えている。

JavaScriptをさらに深くつきつめていく

ここがとても大事だと思っていて、勉強方法としては「ひたすらGitHubをあさって他人のJavaScriptのソースを読む」、「色々な縛りを設けて(外部ライブラリ使用禁止etc)開発をしてみる」とかがある。

毎日時間を設定して上に挙げたようなことをやるってのを日課にすればちゃんと積み重なっていくと思われる。

流行り廃りの関係の無いITの基礎を勉強する

一番大事であるはずだけれどなかなか気合いが入りづらいのがここで。
1年近く前に、基本情報技術者試験を受けるためにその試験対策の勉強をしたのだけれど、あれは仕事で役に立っているかと言われればそんなことはないけれど確実に意味があったと思っている。

そんな感じでまた目標を作れば腰を据えてここらへんの勉強をできるかなと。とりあえず次は応用情報技術者を受ければ良いんだろうなとは思うけれど、まあ今のドタバタ(仕事周りで色々ある最近)が落ち着いたらって感じになってしまう。

そうやって後に後にまわしてしまうのがこのジャンルなので、やるやる詐欺だけは避けなければ。

はい、そんな感じで以上の4つを優先度つけつつバランスよく勉強していこうと考えています。

本題

そんなわけで最近はよくpaizaとかがやっているプログラミング問題とか見ると、じっくり眺めたくなっている。
そこでこんな問題を見つけた。

配列を引数に受けて、和を返す関数と二乗和を返す関数と三乗和を返す関数を作りなさい。

問題とともにいろんな人の回答がすでに載っていて僕が考える間もなく答えを見てしまったのでアレではありますが、美しいなあと思う回答もいくつかありつつもなんかまだつきつめられそうな気がするっていう回答ばかりだった。

そんなわけで良い感じの回答を拾ってそこから自分なりに色々手を加えまくって作ったのがこれ。

const sigma = f => array => [0, ...array].reduce((acc, current) => acc + f(current));
const sum = sigma(n => n);
const sqSum = sigma(n => n * n);
const cubeSum = sigma(n => n * n * n);

sum([1, 2, 3, 4]);  // 10
sqSum([1, 2, 3, 4]); // 30
cubeSum([1, 2, 3, 4]); // 100

関数を引数に受けて関数を返すsigmaという関数を作っていて、これが鍵になっている。
ちなみにこういうsigmaのような関数のことを 高階関数 と呼ぶらしい。

高階関数(こうかいかんすう、英: higher-order function)とは、関数(手続き)を引数にしたり、あるいは関数(手続き)を戻り値とするような関数のことである。

高階関数 - Wikipedia

問題に対する答えとしては、たった4行で作ることができた。ひとえにこれはES2015から実装されているarrow functionのおかげだ。
この回答をarrow function無しで実装すると以下のようになる。

const sigma = function(f) {
  return function(array) {
    return [0, ...array].reduce(function(acc, current) {
      return acc + f(current);
    });
  };
};
const sum = sigma(function(n) {
  return n;
});
const sqSum = sigma(function(n) {
  return n * n;
});
const cubeSum = sigma(function(n) {
  return n * n * n;
});

returnだらけだ…。
今更だけれど、arrow functionは単純なfunctionという文字の省略ではなく、「thisのbind」と「statementが一つだけの場合は波括弧とreturnを省略する」という構文です。

そんなわけでarrow functionのおかげでArrayのメソッドがとても書きやすくなったりする。
この回答もarrow functionのおかげであそこまで綺麗になった。

ちなみに#1

reduceの引数に渡す関数の引数は現在(acc, current)になっているが、最初は(pre, current)にしていた。
これを同僚に見せたところ、reduceに渡す関数の引数は(前の値, 今の値)ではなく、正確には(累積値, 今の値)であるので、preではなくacc(アキュムレータ)を使うべきということを言われた。

腹落ちしたのでそれに変更している。

アキュムレータ(英: Accumulator)は、コンピュータにおいて、演算装置による演算結果を累積する、すなわち総和を得るといったような計算に使うレジスタや変数のことである。

アキュムレータ (コンピュータ) - Wikipedia)

ちなみに#2

[0, ...array]という構文があってわかりづらいとは思うが、これはreduceの最初にaccに入ってくる値を渡された配列の一番最初の値ではなく、0にしたかったためだ。
そのために、渡されたarrayにいい番最初に0を結合している。
でないと、渡された配列の1番最初の値を2乗・3乗することができなくなってしまうので。

しかしこれには問題がありそうな気がして

確かに回答としては4行にまとまっているし、僕としては綺麗だなーと思うコードになっている。
けれど、sigma関数を定義する部分がぱっと見では多分何をしているかが伝わりづらい。読み取る側のスキルが求められるし、果たしてそれはチーム開発をする上で考えると良いコードと言えるのだろうか。

とか考えていたら何が良いコードなのかわからなくなってきた。
短いのは良いことだしかっこいいアプローチには憧れる。しかしわかりやすくなければチーム開発の障壁になるし、それは単純にみんながこれをぱっと見でわかるようになるべきって話にはならないと思う。

うーん、わからん。
これに関してはいろんな人の意見を聞いてみたい。

何か意見があれば教えてくれるとありがたいです。
ていうかそもそももっと良いコードにできるよ、とかの意見も待っております。

まとめ

今日はarrow functionの話になったけれどとにかく僕が言いたいこととしてはスキルアップしたいというそれだけなのである。
自分なりに考えたり友達に聞いたりして今は良い方法を模索しながら勉強している。

こういうやり方で自分は勉強してったよって話とかももしあれば教えていただけると嬉しいです。

こちらからは以上です