ESLint: operator-assignment の「くだらない話」2

なんか…

結構全体みたので他にもちょっと気になるものも見かけたけれど、「Good! for this rule」としてこんなの書かれると弱ってしまう:

1 x[foo()] = x[foo()] % 2;

“always” ならこうなんではないの?:

1 x[foo()] %= 2;

と思うのは「正常」だが、多分「”always” で是とみなされるステキな」こんなコードを書いたプログラマは、チームの仲間から殺される。

こういうことな:

 1 [me@host: ~]$ node
 2 > function foo() {
 3 ...   return Math.random();
 4 ... }
 5 undefined
 6 > foo()
 7 0.5832712487769784
 8 > foo()
 9 0.24636033092813614
10 > var x = {};
11 {}
12 > x[foo()] = x[foo()] + 1;
13 NaN
14 > x
15 { '0.5106215654162429': NaN }

今の例の場合は foo() が呼ばれるたびに異なる値を返しうることを ESLint は「知っている」というわけだ。

評価順にも関係するかな? 今の場合、こういう順序で評価されている?:

  1. 左辺x のプロパティ参照内の foo() 呼び出し
  2. 左辺x オブジェクトに 1. でプロパティ参照 (初登場なので挿入される)
  3. 右辺x のプロパティ参照内の foo() 呼び出し
  4. 右辺x オブジェクトに 3. でプロパティ参照 (初登場なので undefined)
  5. めでたく「右辺x[初登場キー] = undefined + 1」と解釈される

1.、2. と 3.、4. は逆かしら? foo() を書き換えてみればわかるか。

 1 [me@host: ~]$ node
 2 var idx = 0;
 3 > function foo2() {
 4 ...   var res = idx;
 5 ...   idx += 1;
 6 ...   return res;
 7 ... }
 8 undefined
 9 > var y = {};
10 undefined
11 > y[foo2()] = y[foo2()] + 1;
12 NaN
13 > y
14 { '0': NaN }

だね。

例えばパラメータリストの評価順序、みたいなこともそうで、ES6 ではデフォルト引数を書けるみたいなことを ESLint ドキュメント内で読んだ気がするので、たぶんそこでも問題になると思うが、要するに「常識的なプログラマなら絶対に避けているので、そういったプログラマほどこれを読んで理解出来ない」という性質のもんである、挙げた例は。すなわち「質が高いプログラマほど、こうやって詳細検討してみないと真意を読み取れない」。それともなんだ、「バカどうしだと心が通じ合う」か? こういう「繊細」な振る舞いに「依存して書けるオレ、かっけー」(16進数理解出来るオレ、カッケーと同類)。

多分以下も本質的に同類:

1 var x = 0;
2 var y = {};
3 y[x] = y[++x];

関数呼び出しほどには不自然さはないが、結局これも「皆で共有出来る」ことはない。いつかは誰かが疑って検証作業を強いられるハメになる。

こういうのも宗教論争の種になってしまうんだろうなぁとは思うけれど、こういうの、自分で書きながらどう一瞬の判定を下していくか、てのは結局「この一行だけ取り出して検証作業を強いられる可能性がある、読み手を悩ませる書き方かどうか」を意識するかどうか、ということにはなるんだけれど、後者の例はワタシもやってしまうかもしれん。(そして数ヵ月後・数年後に自分の書いたもので悩む、のだろう。)