TOMLで浮動小数点数の指数部分でleading zeroが許可される

github.com

これがTOMLの作者(Tom Preston-Werner)の手によってマージされていた。一応masterブランチにマージされてもリリースまでにrevertされる可能性はあるとはいえ、それなりの確率でTOML 1.0.0でリリースされると思われる。

この変更で、以下のようなTOMLファイルが合法になる。

fp0 = 1.0e01
fp1 = 1.0e+01
fp2 = 1.0e-01

これまで上の書き方は許されず、下のようにするしかなかった。

fp0 = 1.0e1
fp1 = 1.0e+1
fp2 = 1.0e-1

だが、多くの言語で指数表記(C++ならsciencitific)を指定すると上の書き方になる。printfでも%eを使うと、指数の桁は最低2桁となり、上の表記になる。

なので拙作のtoml11でも、上の書き方のファイルには文法違反のエラーを出していたし、シリアライズの際はleading zeroが入っていたら検出して消すためのコードを追加していた。これはあきらかに面倒だった。常に小数表記にしたらどうか、とも一瞬考えたが、明らかに読みにくいファイルが生成されてしまうのでだめだ。指数表記が適している場合というのは多く存在する。アボガドロ数なんかを小数表記で出力することを考えてみるとわかると思う。

これに困るのはCやC++だけではない。このPRの元になったIssueで議論していた人が使っていたのはPythonだ。自作Pythonスクリプトで自動生成したファイルがTOMLパーサにリジェクトされるのはつらい、というコメントが初期の議論を引き起こしている。

github.com

Issueのコメントでは、Rubyでputsをしても上の表記になるとの指摘がある。後続のコメントからはLuaHaxeもそうらしいし、ちょっと見た限りGoもそうだ。Rustは違うが(!)。みんな困っていたわけだ。

初期の議論では、「leading zeroを許すと8進数表記と区別がつかないので筋が悪い」「整数ならそうだが、浮動小数点数でexponentで8進数が使われたことはない」のような議論があったのち、作者(Tom)が現れて「整数に関してleading zeroは許されていないので、浮動小数点数の一部(の実質的に整数である部分)でだけleading zeroを許すのは文法が複雑化する、特定の言語の出力をサポートするために文法を複雑化するのは「単純な言語」というゴールに反する」と主張し、Issueをクローズしている。

だがその後もこの議論は燃え続けた。「特定の言語の出力をサポートするために」と言うが、実際には殆ど全ての言語が、浮動小数点数を指数表記で出力する際は指数部分を最低2桁にする。「特定の言語」があまり有名でない1つ2つの言語であればまだしも、最も有名で最も使われている言語達の大部分だった場合、多少の言語の複雑化も許容する価値はあるだろう、というような議論が続いた。

ごく最近の、そして決定打になったらしき議論では、殆どの言語がサポートしているということに加えて以下のような主張がされている。「通常使用される物理量は、指数部分が3桁になることはまずない。電子の質量(9.11e-31 kg)や太陽の質量(1.99e30 kg)でも余裕を持って2桁に収まる。だとすると、出力時に最低2桁、符号も必ず書くようにしておくと、浮動小数点数の配列が見目麗しく並ぶことになる」。これは暗にこの変更によって一部のTOMLファイルが読みやすくなると主張しているように思う。さらに、科学技術計算用途でTOMLを使うことが難しくなる、という問題も指摘されており、実際にこのためにTOMLを科学技術計算用途で使うのをやめた人も登場した。

これらの指摘によってTomも納得し、この変更が入ることになった。Tomは特にどのコメントを重く受け止めたかは何も言っていないので、もしかすると単に最初の議論から2年も経って気が変わっただけなのかもしれないが、個人的にはこの変更によって可読性が高まる(数値が綺麗に並ぶ)ケースがあるという主張が重要だったのではないかと思っている。もちろん実際に問題になるケースがかなり具体的に示されたということもあるのだろうが。TOMLは単純でかつ人間にも機械にもわかりやすいことを目指している。なので特定の言語の出力をサポートするためだけに文法を複雑化することはないが、人間にとって読みやすくするために文法を複雑化することは許容される、と考えると、Tomの姿勢はとても一貫した、言語の設計者として理想的なものではないだろうか。

まあ個人的にはこの変更はもっと早くに入って欲しかったけれど。