Revive Number Format Separator RFC

php.internals

Theodore Brown

7 years ago
Is there any chance the Number Format Separator RFC [1] could be revived for PHP 7.4? I looked at the discussion from a few years ago and it's not clear why many people originally voted against it. JavaScript and Python have both gotten this feature recently and it's something I really miss in PHP when declaring/reading large numbers. Maybe it would help to simplify how the restrictions are described in the RFC. As I understand it, the only restriction is that each underscore in a numeric literal must be between two digits. Perhaps the way the RFC described this syntax made it seem more complex than it is. Best regards, Theodore Brown [1]: https://wiki.php.net/rfc/number_format_separator

Bishop Bettini

7 years ago
On Thu, Apr 25, 2019 at 6:07 PM Theodore Brown <theodorejb@outlook.com> wrote:
> Is there any chance the Number Format Separator RFC [1] could be revived > for PHP 7.4? I looked at the discussion from a few years ago and it's not > clear why many people originally voted against it. > > JavaScript and Python have both gotten this feature recently and it's > something I really miss in PHP when declaring/reading large numbers. > > Maybe it would help to simplify how the restrictions are described in the > RFC. As I understand it, the only restriction is that each underscore in a > numeric literal must be between two digits. Perhaps the way the RFC > described this syntax made it seem more complex than it is. > > Best regards, > > Theodore Brown > > [1]: https://wiki.php.net/rfc/number_format_separator
Subsequent conversation occurred on the voting thread [1], which wasn't included by reference in the RFP itself. The only dissent I saw in that thread came from Pascal Martin, speaking for AFUP, who wrote [2]:
> it would be harder to search in code, as there would be more than > one way to write a number. Basically, it would break grep/find. > Splitting numbers so they are more readable is kind of a presentation > matter and, as such, could be done by an editor/IDE when displaying > code, without having to modify the code by hand
Related: the RFC author Tom Punt also detailed the implementation, but didn't incorporate that by reference into the RFC [3]. Worth the read. With Tom's blessing, I'd support re-visiting this feature. It's useful, IMO. [1]: https://marc.info/?l=php-internals&m=145271098232484&w=2 [2]: https://marc.info/?l=php-internals&m=145320709922246&w=2 [3]: https://phpinternals.net/articles/implementing_a_digit_separator

Bishop Bettini

7 years ago
On Thu, Apr 25, 2019 at 9:28 PM Bishop Bettini <bishop@php.net> wrote:
> On Thu, Apr 25, 2019 at 6:07 PM Theodore Brown <theodorejb@outlook.com> > wrote: > >> Is there any chance the Number Format Separator RFC [1] could be revived >> for PHP 7.4? I looked at the discussion from a few years ago and it's not >> clear why many people originally voted against it. >> >> JavaScript and Python have both gotten this feature recently and it's >> something I really miss in PHP when declaring/reading large numbers. >> >> Maybe it would help to simplify how the restrictions are described in the >> RFC. As I understand it, the only restriction is that each underscore in a >> numeric literal must be between two digits. Perhaps the way the RFC >> described this syntax made it seem more complex than it is. >> >> Best regards, >> >> Theodore Brown >> >> [1]: https://wiki.php.net/rfc/number_format_separator > > > Subsequent conversation occurred on the voting thread [1], which wasn't > included by reference in the RFP itself. > > The only dissent I saw in that thread came from Pascal Martin, speaking > for AFUP, who wrote [2]: > > it would be harder to search in code, as there would be more than > > one way to write a number. Basically, it would break grep/find. > > Splitting numbers so they are more readable is kind of a presentation > > matter and, as such, could be done by an editor/IDE when displaying > > code, without having to modify the code by hand > > Related: the RFC author Tom Punt also detailed the implementation, but > didn't incorporate that by reference into the RFC [3]. Worth the read. > > With Tom's blessing, I'd support re-visiting this feature. It's useful, > IMO. > > [1]: https://marc.info/?l=php-internals&m=145271098232484&w=2 > [2]: https://marc.info/?l=php-internals&m=145320709922246&w=2 > [3]: https://phpinternals.net/articles/implementing_a_digit_separator >
Using a variant of Nikita's top packages visitor [1], the top 250 packages contain about 3 million integer literals. Of those, about 800k have 5 or more digits, while only about 3k have 10 or more digits. Nine digits is unusually common, because of its use in giggsey/libphonenumber-for-php for United States phone numbers. Applying some rough heuristics to file names, 89% of those literals appear in a data file, 8% in code, and 3% in tests. A cursory scan of current usage suggests that number format separator might be used in scenarios such as: Phone numbers 919_555_1234 49_89_636_48018 Date time values 2018_04_26 20180426_183242 Range end points (using any locale's grouping strategy) 2_147_483_647 1_67_77_215 Nibble groups 0b0011_1111_0100_1110 For those first few, Kotlin has similar examples [2], but Javascript discourages use of number separator in "number-ish" values (eg phone numbers) [3]. https://gist.github.com/bishopb/157d403dc1c190957a558c93e120a07d [1]: https://gist.github.com/nikic/a2bfa3e2f604f66115c3e4b8963a6c72 [2]: https://kotlinlang.org/docs/reference/basic-types.html#underscores-in-numeric-literals-since-11 [3]: http://2ality.com/2018/02/numeric-separators.html

Rowan Collins

7 years ago
> > On Thu, Apr 25, 2019 at 6:07 PM Theodore Brown <theodorejb@outlook.com> > > wrote: > > > >> Is there any chance the Number Format Separator RFC [1] could be revived > >> for PHP 7.4? I looked at the discussion from a few years ago and it's > not > >> clear why many people originally voted against it. >
Hi, I'm not particularly against this proposal, but I'm not sure how often I'd use it. On Fri, 26 Apr 2019 at 06:15, Bishop Bettini <bishop@php.net> wrote: A cursory scan of current usage suggests that number format separator might
> be used in scenarios such as: > > Phone numbers > 919_555_1234 > 49_89_636_48018 >
This is a poor example, because phone numbers shouldn't be stored as integers; there's nothing you can do with them mathematically, and outside of North America it's extremely common for them to have significant leading zeroes.
> Date time values > 2018_04_26 > 20180426_183242 >
Again, I can't see why you'd ever use an integer for that, rather than a string. Were there really integer literals of this form in the packages you searched?
> For those first few, Kotlin has similar examples [2], but Javascript > discourages use of number separator in "number-ish" values (eg phone > numbers) [3]. >
The second article you link to isn't official documentation, just someone's blog post about the feature. I agree with the comment, though - the Kotlin example of a credit card number wouldn't pass code review with me, because they're not really "numbers", they're identifiers which happen to only use digits (the only mathematical operation on a card number would be checking the Luhn checksum, which is a digit-by-digit operation anyway). The only example that I can see myself using is the one of money-as-cents (or, in my case, pence): $pricePence = 1000_00; // GBP 1000.00 Although some kind of struct with separate fields and overloaded operators would probably be better still: $price = Money{ 'GBP', 1000, 00 }; The main use I've had for large number literals is for things like cache lifetimes, where the extra syntax wouldn't help, but constant expressions do: $lifetimeSecs = 604800; // 7 days const SECONDS_IN_MINUTE = 60; const SECONDS_IN_HOUR = SECONDS_IN_MINUTE * 60; const SECONDS_IN_DAY = SECONDS_IN_HOUR * 24; $lifetimeSecs = 7 * SECONDS_IN_DAY; Similar approaches work for other contexts, for instance: const GIBIBYTE = 1024 ** 3; const GIBIBYTE = 2 ** 30; both read more clearly than anything you could do with underscores: const GIBIBYTE = 1_073_741_824; const GIBIBYTE = 0x40_000_000; const GIBIBYTE = 0b1_00000_00000_00000_00000_00000_00000; Regards,
-- Rowan Collins [IMSoP]

Lester Caine

7 years ago
On 26/04/2019 12:10, Rowan Collins wrote:
> This is a poor example, because phone numbers shouldn't be stored as > integers; there's nothing you can do with them mathematically, and outside > of North America it's extremely common for them to have significant leading > zeroes.
Along with flagging the country code with a '+' ...
-- Lester Caine - G8HFL ----------------------------- Contact - https://lsces.co.uk/wiki/?page=contact L.S.Caine Electronic Services - https://lsces.co.uk EnquirySolve - https://enquirysolve.com/ Model Engineers Digital Workshop - https://medw.co.uk Rainbow Digital Media - https://rainbowdigitalmedia.co.uk

Theodore Brown

7 years ago
On Fri, Apr 26, 2019 at 6:10 AM Rowan Collins <rowan.collins@gmail.com> wrote: > On Thu, Apr 25, 2019 at 6:07 PM Theodore Brown <theodorejb@outlook.com> wrote: > > > Is there any chance the Number Format Separator RFC [1] could be revived > > for PHP 7.4? I looked at the discussion from a few years ago and it's > > not clear why many people originally voted against it. > > > I'm not particularly against this proposal, but I'm not sure how often I'd > use it. How often you use numeric separators depends on what you are doing. I definitely agree that phone numbers and dates are not good use cases, and that there are usually better ways to write things like the number of seconds in a day or number of bytes in a gigabyte. However, there are many other appropriate uses of large integers where numeric separators can make the code more readable and prevent mistakes. Here's an example from code I maintain: ```php function getActiveDirectoryTimestamp(DateTime $date): int { // Active Directory stores dates as the number of 100-nanosecond // intervals since January 1, 1601. $epochDiff = 11_644_473_600; $secondsAfterADEpoch = $date->getTimestamp() + $epochDiff; return $secondsAfterADEpoch * 10_000_000; } ``` Another common use case is constants used in scientific calculations: ```php const ASTRONOMICAL_UNIT = 149_597_870_700; const SPEED_OF_LIGHT = 299_792_458; echo 'Time for light to travel from sun to earth: '; echo (ASTRONOMICAL_UNIT / SPEED_OF_LIGHT) . ' sec.'; ``` For me personally the most frequent use case is actually in tests, where various values (e.g. large dollar amounts) are passed to functions in order to validate business logic. Numeric separators would help make such unit tests a lot more readable. Best regards, Theodore Brown

Thomas Punt

7 years ago
Hi!
> On Fri, Apr 26, 2019 at 4:30 PM Theodore Brown <theodorejb@outlook.com> wrote: > > > On Fri, Apr 26, 2019 at 6:10 AM Rowan Collins <rowan.collins@gmail.com> wrote: > > > > I'm not particularly against this proposal, but I'm not sure how often I'd > > use it. > > How often you use numeric separators depends on what you are doing. > I definitely agree that phone numbers and dates are not good use cases, > and that there are usually better ways to write things like the number > of seconds in a day or number of bytes in a gigabyte.
Storing dates in an integer format can be a valid use case if performance is a concern. It is far faster and more compact to store and compare integer-based dates than using objects for everything. Anyway, if anyone would like to revive this RFC, then feel free to! Thanks, Tom

Rowan Collins

7 years ago
On 27/04/2019 12:18, Thomas Punt wrote:
> Storing dates in an integer format can be a valid use case if > performance is a > concern. It is far faster and more compact to store and compare > integer-based > dates than using objects for everything.
The only way I've seen dates stored as integers is as a number of seconds / milliseconds / whatever since some epoch, most commonly seconds since 1970-01-01 00:00:00 UTC The format Bishop seemed to be suggesting would be absolutely useless for anything other than the simplest comparisons: how do you add a day to the date-as-number 20190430? I'm sure there are use cases for this syntax, but the examples in that e-mail were poorly chosen. Regards,
-- Rowan Collins [IMSoP]

Lester Caine

7 years ago
On 27/04/2019 13:37, Rowan Collins wrote:
> The only way I've seen dates stored as integers is as a number of > seconds / milliseconds / whatever since some epoch, most commonly > seconds since 1970-01-01 00:00:00 UTC
Use of a days count rather than a seconds count makes dates a lot easier to work with. 2 32bit numbers give a substantial day count along with either fractional time of day or alternatively a second count for the day. Genealogical data is substantially easier to manage as a day count which can be expanded in accuracy with a time count either viewed as integers or as floating point numbers ... leap seconds just get hidden in the processing.
-- Lester Caine - G8HFL ----------------------------- Contact - https://lsces.co.uk/wiki/?page=contact L.S.Caine Electronic Services - https://lsces.co.uk EnquirySolve - https://enquirysolve.com/ Model Engineers Digital Workshop - https://medw.co.uk Rainbow Digital Media - https://rainbowdigitalmedia.co.uk

Rowan Collins

7 years ago
On 27 April 2019 13:51:11 BST, Lester Caine <lester@lsces.co.uk> wrote:
>On 27/04/2019 13:37, Rowan Collins wrote: >> The only way I've seen dates stored as integers is as a number of >> seconds / milliseconds / whatever since some epoch, most commonly >> seconds since 1970-01-01 00:00:00 UTC > >Use of a days count rather than a seconds count makes dates a lot >easier >to work with. 2 32bit numbers give a substantial day count along with >either fractional time of day or alternatively a second count for the >day.
That makes sense, but it's still a variant on the epoch + count concept, not year-month-day as in Bishop's example. As such, it still wouldn't particularly benefit from separators; you'd probably write constants in string form and convert them on the fly, or have durations which were multiples of 7 or 365 rather than powers of 10 or 16. Regards,
-- Rowan Collins [IMSoP]

Stas Malyshev

7 years ago
Hi!
> A cursory scan of current usage suggests that number format separator might > be used in scenarios such as: > > Phone numbers > 919_555_1234 > 49_89_636_48018
Just noting here that using integers as phone numbers is not something we want to support, enable or promote.
> Date time values > 2018_04_26 > 20180426_183242
Same here, these are not integers (or numbers).
> Range end points (using any locale's grouping strategy) > 2_147_483_647 > 1_67_77_215
These are numbers, but should be only ever used in constants (with appropriate comment). I am not exactly against this feature, but the potential for abuse - like enabling people using integers for things that are not integers and should not be stored as integers - worries me now.
-- Stas Malyshev smalyshev@gmail.com

Theodore Brown

7 years ago
On Sat, Apr 27, 2019 at 10:25 PM Stanislav Malyshev <smalyshev@gmail.com> wrote: > I am not exactly against this feature, but the potential for abuse > \- like enabling people using integers for things that are not > integers and should not be stored as integers - worries me now. Based on the usage analysis Bishop did, people already use integers for number-like values (e.g. phone and social security numbers) that can be better represented in other ways. Perhaps adding the numeric separator feature can actually be an opportunity to discourage such misuse. We can add a paragraph to the RFC (and the documentation if it is accepted) that lists examples of usage that should be avoided. Ultimately there remains many legitimate uses of large numbers in code (e.g. scientific constants, unit test values, business logic thresholds, etc.), and this feature is a simple way to improve their readability. I've lost count of the number of times I've been debugging a failing test and struggling to count the number and position of digits to make sure I have the right value. This feature would save time when reading code and indeed prevent a lot of mistakes in the first place.

Bishop Bettini

7 years ago
On Sun, Apr 28, 2019 at 1:47 PM Theodore Brown <theodorejb@outlook.com> wrote:
> On Sat, Apr 27, 2019 at 10:25 PM Stanislav Malyshev <smalyshev@gmail.com> > wrote: > > > I am not exactly against this feature, but the potential for abuse > > \- like enabling people using integers for things that are not > > integers and should not be stored as integers - worries me now. > > Based on the usage analysis Bishop did, people already use integers > for number-like values (e.g. phone and social security numbers) that > can be better represented in other ways. > > Perhaps adding the numeric separator feature can actually be an > opportunity to discourage such misuse. We can add a paragraph to the > RFC (and the documentation if it is accepted) that lists examples of > usage that should be avoided. > > Ultimately there remains many legitimate uses of large numbers in > code (e.g. scientific constants, unit test values, business logic > thresholds, etc.), and this feature is a simple way to improve their > readability. > > I've lost count of the number of times I've been debugging a failing > test and struggling to count the number and position of digits to > make sure I have the right value. This feature would save time when > reading code and indeed prevent a lot of mistakes in the first place. >
Well said. One need not agree with an implementation to appreciate the improved readability. If you'd like to re-open this for voting, I'm able to assist with the RFC process and any code changes.

Theodore Brown

7 years ago
On Mon, Apr 29, 2019 at 2:33 AM Bishop Bettini <bishop@php.net> wrote: > Well said. > > One need not agree with an implementation to appreciate the improved > readability. > > If you'd like to re-open this for voting, I'm able to assist with > the RFC process and any code changes. Thanks! I drafted a preliminary RFC, but I'll need assistance with the implementation and publishing the RFC on wiki.php.net. https://gist.github.com/theodorejb/653221e3221b2b4d2ad8fa94d3a963ff

Bishop Bettini

7 years ago
On Tue, Apr 30, 2019 at 4:41 PM Theodore Brown <theodorejb@outlook.com> wrote:
> On Mon, Apr 29, 2019 at 2:33 AM Bishop Bettini <bishop@php.net> wrote: > > > Well said. > > > > One need not agree with an implementation to appreciate the improved > > readability. > > > > If you'd like to re-open this for voting, I'm able to assist with > > the RFC process and any code changes. > > Thanks! I drafted a preliminary RFC, but I'll need assistance with > the implementation and publishing the RFC on wiki.php.net. > > https://gist.github.com/theodorejb/653221e3221b2b4d2ad8fa94d3a963ff
Excellent. I hope we can make the case this time. Please request Wiki karma [1], and we'll iterate on it there. [1]: https://wiki.php.net/rfc/howto