Pythonを闇改造した

思いつきをざっと書いて公開してしまうシリーズ2

Python 3.10 ではこれまでPythonのコンパイルの仕組みが変わり、従来の貧乏くさいLL(1)パーザから PEGパーザに切り替えられる予定になっています。

新パーザはすでにPython3.9に含まれていて、現在のPython 3.9b1でも試せるようになってますので、早速試してみました。

https://github.com/atsuoishimoto/cpython/pull/2

JSON Literal

Pythonのプログラムを書いていて、辞書オブジェクトを書くのってけっこう面倒な事が多いです。たとえば、なにかのWebサービスでデータをJSONで送りつけるとき、こんな感じになります。

def register_user(first, last, addr1, addr2):
    d = {'first': first,
         'last': last,
         'addr1': addr1,
         'addr2': addr2,
         'tel': '123-456-789'}

    requests.post(URL, d)

同じ単語の繰り返しがうざいですね。文字数の半分近くは単なる繰り返しです。文字数のわりに情報量がすくなくてイラッとします。こまめに '' 入ってるのも鬱陶しいです。RESTなWebサーバのテストとか書いてるとこんなのが山ほど出てくるので、だいぶイラつきます。

dict 型を直接呼び出すとちょっとだけマシになります。

d = dict(first=first,
         last=last,
         addr1=addr1,
         addr2=addr2,
         tel='123-456-789')

これ、JavaScriptだと、こんな感じに書けてスッキリしてます。

d = {first, last, addr1, addr2, tel:'123-456-789'}

これと似たような書き方をPythonでもできないかなぁと思ってやってみたのが、上記のパッチです。辞書リテラルの動作を変えるのは無謀なので、${...} の形式で書けるようにしてみました。普通の辞書のように、文字列などを辞書のキーに指定すると SyntaxError になります。

d = ${first, last, addr1, addr2, tel:'123-456-789'}

はじめてPEG パーザのコードを書いてみたけど、調べはじめて一時間かそこらでここまで書けました。従来のように、CSTを作ってからASTに変換するのではなく、直接ASTを出力するのでわかりやすくていいです。

最初は

d = j{first, last, addr1, addr2, tel:'123-456-789'}

のように j を接頭文字にしてて、 旧Parserならそれで動いたんだけどPEGパーザだとなぜか動かないんで $ にしてます。なんで動かないかは未調査… $ 以外だと使える記号は ?` ぐらいで、まあこん中から選ぶなら $ が一番マシかな、ぐらいの感じで使ってます。