Edited at

YAMLの60進数の罠

さて、突然ですが、このYAMLをRubyでパースするとどのような結果になるでしょうか?

hoge: 12:34

多くの人は {"hoge" => "12:34"} という結果になると思いますが、実は違います。

このYAMLのパース結果は、{"hoge" => 754} です。

この記事の後半では754 という謎の数字の正体に迫って見ようと思います。


仕様書確認

とりあえず、YAMLの仕様書を確認してみます。

こちらが最新版のYAML仕様書なので、この中にそれっぽい仕様があるかどうかを確認してみます。

YAML Ain’t Markup Language (YAML™) Version 1.2

ですが、このドキュメントを読んでも、この挙動に関する記述は見つからなかったです・・・


ソースコード確認

さて、仕様書を見てどうも解決しかなったので、ソースコードを読んでみましょう。

読み取った文字列の雰囲気を見て、いい感じにいろんな型に変換変換している部分に謎を解く鍵が見つかりました。

https://github.com/ruby/psych/blob/master/lib/psych/scalar_scanner.rb#L85

この部分の処理によって、文字列を整数型に変換しています。

そして、 60 というマジックナンバーが登場していることも分かります。


仕様書確認 Again

ここで、Rubyのドキュメントを見ると、次のように書かれていました。

https://docs.ruby-lang.org/ja/latest/library/yaml.html


psych ライブラリ: YAML バージョン 1.1 を扱う事ができます。


バージョン 1.1

最初に確認していた仕様書のバージョンは1.2でしたので、バージョンが違いました。

というわけで、バージョン1.1の仕様書を確認してみたところ、答えを見つけました。

YAML Ain’t Markup Language (YAML™) Version 1.1

数値を : 区切りで書くことによって、sexagesimal(60進数)で書くことができるようになるようです。

ソースコードに書かれていた 60 というマジックマンバーの正体はこれです。

754 という謎の数字の正体は 60*12+34 だったんです。


まとめ


  • YAMLで文字列を書くときには念のために " で囲むのがベター

  • いつも使っているYAMLといえども、仕様書を読むといろんな発見がある