PythonとJavaScriptを双方書く人へ、混乱を防ぐためのコーディング規約的なtips

私は Python が第一言語で、JavaScript が第二言語だ。でも、仕事のタイミングによっては JavaScript ばかり書いている時期というのもあって、Python のコードに `;` を書いてしまったり、Python のコードでやたら無名関数を使いたくなったり、ちょっとしたフラストレーションを感じることがある。

基本、言語というものは言語ごとの理屈があるのだから、それぞれの言語の書き方をすればいい。自然言語でも、外来語だからと日本語の中のカタカナ語を英語として発音してしまったら違和感を感じるように、完全なバイリンガルは以下のようなことを愚かしいと思うかもしれない。

このように前置きしたうえで、混乱を防ぐためにできることを4つ列挙してみる。

## JavaScript で `;` は基本書かないようにする

真っ初めから JavaScript ネイティブの方には怒られそうなtipsだ。JavaScript には自動セミコロン挿入という機能があり、改行を適切に使えばほとんどの場合、セミコロン無しでも問題にならない。問題になり得る代表的な例としてよく挙げられるのは、

```JavaScript
a = b + c

(function() {
    …
})()
```

の `(function` 以降が `c` の引数だと解釈されてしまう問題だが、そもそもグローバルの汚染を防ぐためのハックである `(function() {…})()` 記法をやめてしまえばよい。

```JavaScript
a = b + c

myapp.main = function() {
    …
}
myapp.main()
```

このようにモジュールパターンを使って書いていけばグローバル汚染の問題は生じない。

この書き方のデメリットとして `const` と書いて関数の上書きを防ぎたいという欲求は満たされなくなってしまう。`const myapp.main` はエラーになってしまうからだ。適切にプロパティの階層を分けるなどして、管理できるように整理することが必要になる。

`(function() {…})()` 記法についてはこれで解決するが、頭に `(` がきてしまうのはそう特別なことではなくて、

```JavaScript
a = b + c
(d + e).print()
```

とかいろいろあり得る。for文のヘッダー `for ( ... ; ... ; ... )` はもちろんのことながら、必要な時に `;` を書くことを躊躇わないことも重要な考え方だ。どうしてもそこを統一したいというならば、[Nim](https://nim-lang.org/) のような JavaScript にコンパイルできる別言語を使うべきだ。

ちなみに、このセミコロン無しというのはどちらかというと劣勢であるが、[JavaScript Standard Style](https://standardjs.com/)というコーディング規約では正式に推奨されていたりする。

- [node.js のスタイルガイド](https://github.com/felixge/node-style-guide#use-semicolons)
- [jQuery のスタイルガイド](https://contribute.jquery.org/style-guide/js/#semicolons)
- [Google のスタイルガイド](https://google.github.io/styleguide/jsguide.html)
- [Airbnb のスタイルガイド](https://github.com/airbnb/javascript#semicolons)

といった有名どころのスタイルガイドではセミコロン有りを推奨している。

**参考:**

- [JavaScriptの行末セミコロンは省略すべきか | blog.tai2.net](https://blog.tai2.net/automatic_semilocon_insertion.html) `!` で `(function() {…})()` の解決をすることに対する批判とかはその通りだと思う。`!` は Boolean を逆転させる効果があるため後に続く部分を Boolean として評価しようとするのを使った Dirty Hack でしかない。
- [【脱初心者JavaScript】名前空間のイロハ - Qiita](https://qiita.com/kenju/items/0d8f85df205ea4978508) プロパティに変数や関数を入れていくことで名前空間を分ける方法の詳細
- [handler\.defineProperty\(\) \- JavaScript \| MDN](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Proxy/handler/defineProperty) `const` の問題は Python でいう `__setattr__` 相当のものを書くことで関数の上書きを防ぐことはできるかも。[Object\.freeze](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze) では凍結が浅くて用をなさないです。

## インデントはエディタに任せる（か好きにする）

Python は PEP8 という公式のスタイリングガイドがあって、[1レベルインデントするごとに、スペースを4つ使いましょう](https://pep8-ja.readthedocs.io/ja/latest/#id4)と書かれている。

一方の JavaScript は公式というものはなく、[調査によるとインデントはスペース2個と定めている場合が多いよう](https://ics.media/entry/10234)だ。

どちらかに揃えたければ、好きなほうを選べばよいと思う。Python についても [Google はスペース2個を内部の規約で使っていた](https://www.reddit.com/r/learnpython/comments/1xfoxz/pep_indentation_using_4_spaces_vs_googles_2_spaces/)ということもあるし、そこまで神経質に4にこだわることはないだろう。

そもそも、私はインデントについては揃えていない。Atomをよく使うので、[エディタにインデントのスペースの数を言語ごとに指定する方法](https://qiita.com/Halkey/items/8db5cb35a48527c4c528)が備わっていれば、それを利用すればよく、あまり表題のような混乱は生じないからだ。ちなみにAtomのオートインデントは `ctrl+i` で JavaScript を書くときには多用する。

## 無名関数はシンプルな場合のみ。複雑になるときは名前付きの関数を定義

JavaScript では無名関数を多用する。`function(){…` という書き方はもちろん、`(param1, param2, …, paramN) => { statements }` というアロー関数の書き方はとても便利だ。後者は `this` などの特別なオブジェクトが拘束されないというメリットもある。

> アロー関数が登場するまでは、関数ごとに自身の this の値を定義していました(コンストラクタでは新しいオブジェクト、strict モード の関数呼び出しでは undefined、「オブジェクトのメソッド"」として呼び出された関数ではそのときのオブジェクト、など)。これは、オブジェクト指向プログラミングをする上で煩わしいということが分かりました。

from [アロー関数 - JavaScript | MDN](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Functions/Arrow_functions)

さて、Python で無名関数と言えば lambda 式だが、[Guido は Python3 から lambda 式を除去したがっていた](https://www.quora.com/Why-did-Guido-van-Rossum-want-to-remove-lambda-from-Python-3)という話がある。

ここで、

- 処理がシンプル
- 一度きりしか使わない

ものだけ lambda 式で書いて、それ以外のものはちゃんと関数として別定義すれば可読性が低くなることは避けられる。そして、JavaScriptの方でも、アロー関数の中が複雑になるようならば、大抵は関数を分けたほうが可読性は高くなる。

**余談めいた参考:**

- [PEP 3107 -- Function Annotations | Python.org](https://www.python.org/dev/peps/pep-3107/#lambda) Python には `->` アロー関数に似たという記法が存在するが、これは関数アノテーションという全くの別物。
- [Guido was right, there should be no lambda in Python.](http://www.paulbrownmagic.com/blog/vslambda) Haskell みたいに書けないから Lambda 式の本来の意味をなしておらず、無理にカリー化を書こうとすると non-Pythonic になってしまうという指摘。

## 変数の命名規則はそれぞれの言語に従い、linter を使う

Python の PEP8 でクラス名は CapWords を使うことが推奨されている。これは JavaScript でも一般的だ。

関数や変数については

> mixedCase が既に使われている (例: threading.py) 場合にのみ、互換性を保つために mixedCase を許可します。

と書かれていて、かなり強く snake_case を使うことが推奨されている。JavaScript の場合は camelCase が多くのコーディング規約で推奨されている。この命名規則は広範囲に及んでいるため、ライブラリやモジュールを使う時点で、それぞれの言語において、主流である命名規則の変数がコードの中に入ってくることは避けられないだろう。

また、自分が GitHub に置いて使ってもらう側に立つことを考えても、自分が使っている言語の組み合わせを理由にして他人のコードを汚染するのはあまり嬉しくない。この他の人への影響の有無が`;`の話とは異なる。よって、こちらは「統一せずに、それぞれの言語で主流な命名規則に従う」という判断が真っ当だろうと思う。

しかし、ここが最も混乱するところで、JavaScript で snake_case、Python で camelCase の変数を無意識に書きがちでもある。インデントの話もそうだったが、命名規則に従っているかのチェックはエディタやコンパイルの環境で対処するしかないと思う。結局 [ESLint](https://eslint.org/) 使いましょうというありきたりな解決策に至ってしまった。以下は、`;` を書くとエラーになるようにし、変数が camelCase じゃないと warning を出すようにした .eslintrc ファイル。

```json:.eslintrc
{
  "extends": "eslint:recommended",
  "env": {
    "node": true,
    "es6": true
  },
  "rules": {
    "semi": ["error", "never"],
    "no-console": "off",
    "camelcase": ["warn", {"properties": "always"}],
  }
}
```

**参考:**

- [ESLint 最初の一歩 \- Qiita](https://qiita.com/mysticatea/items/f523dab04a25f617c87d#atom) これ見ながら ESLint 入れた
- [semi \- Rules \- ESLint \- Pluggable JavaScript linter](https://eslint.org/docs/rules/semi) ESLint で `;` を付けない書き方に統一するオプションがある
- [Providing a mechanism to perform unsafe fixes · Issue \#7873 · eslint/eslint](https://github.com/eslint/eslint/issues/7873) セミコロンについては `--fix` オプションで自動で修正できるが、camelcase については自動修正は予期しないエラーを引き起こす可能性があるとして修正プログラムが提供されていない。
- [Pythonで変数名をつけるときには予約語だけでなく組み込み関数との衝突も気を付けましょう \- Qiita](https://qiita.com/cm3/items/6a856c44dd92632aa54f) 前に書いた記事