The following code raises an error:
"0".to_i(prefix: true)
Unhandled exception: Invalid Int32: 0 (ArgumentError)
https://play.crystal-lang.org/#/r/6qsn
As far as I can tell from the source, it sees the leading zero and thinks it's an octal.
Then it aborts because it thinks there is no more to the number.
I have a scenario where I'm parsing numbers that may or may not have a prefix,
and using a built-in method is certainly preferred over writing my own.
This is a bit of an odd scenario, since it is expecting a prefix, but the following works:
"5".to_i(prefix: true)
Perhaps this just needs to be documented, but it should be a simple fix.
Crystal version 0.27.2
AFAIK this behaves as per the documentation:
prefix: if true, the prefixes "0x", "0" and "0b" override the base
5 doesn't have a prefix and is parsed as base 10, but 0 happens to be a prefix and the parser expects more digits in base 8.
That being said, I believe we changed octal representation in literals to an explicit 0o. Maybe #to_i should also be changed to reflect that? Or is there a reason this is kept this way?
Yes, I think it's old behavior that we need to change.
Honestly no idea how you guys manage to rationalize an obvious bug.
5doesn't have a prefix and is parsed as base 10, but0happens to be a prefix and the parser expects more digits in base 8.
You just restated what was written in the original post. And indeed, it's what constitutes the bug.
That being said, I believe we changed octal representation in literals to an explicit
0o. Maybe#to_ishould also be changed to reflect that? Or is there a reason this is kept this way?
Could be because to_i is not defined by the syntax of Crystal programming language; its purpose isn't parsing a subset of Crystal.
This is a bug.
I've found that the YAML parser also follows the previous style. It expects 0 as a prefix instead of 0o. Since this goes outside the language, I think both styles should be allowed in YAML parsing.
"0" => 0
"0755" => 0o755
"0o123" => 0o123
Thoughts?
YAML parsing should follow the YAML specification, changing crystal side shouldn't change yaml side
From the core yaml spec, it looks like octal number are like 0o123 like crystal, so the previous yaml octal number handling was wrong?
As far as I understand, YAML spec don't specify how octal numbers should be parsed.
https://yaml.org/spec/1.2/spec.html#scalar/content%20format/
For example, the integer “11” might also be written as “0xB”. Tags must specify a mechanism for converting the formatted content to a canonical form for use in equality testing. Like node style, the format is a presentation detail and is not reflected in the serialization tree and representation graph.
https://yaml.org/spec/1.2/spec.html#tag/repository/int
Canonical Form:
Decimal integer notation, with a leading “-” character for negative values, matching the regular expression 0 | -? [1-9] [0-9]*
the only mention of 0o14 is in the example.
Most helpful comment
AFAIK this behaves as per the documentation:
5doesn't have a prefix and is parsed as base 10, but0happens to be a prefix and the parser expects more digits in base 8.That being said, I believe we changed octal representation in literals to an explicit
0o. Maybe#to_ishould also be changed to reflect that? Or is there a reason this is kept this way?