rfc:numeric_literal_separator
Differences
This shows you the differences between two versions of the page.
Next revision | Previous revision | ||
rfc:numeric_literal_separator [2019/04/30 23:01] – created theodorejb | rfc:numeric_literal_separator [2019/08/19 19:58] (current) – Separators in C# aren't just a proposal theodorejb | ||
---|---|---|---|
Line 1: | Line 1: | ||
====== PHP RFC: Numeric Literal Separator ====== | ====== PHP RFC: Numeric Literal Separator ====== | ||
- | * Date: 2019-04-30 | + | * Date: 2019-05-15 |
- | * Author: Theodore Brown < | + | * Author: Theodore Brown < |
* Based on [[https:// | * Based on [[https:// | ||
- | * Proposed PHP version: PHP 7.4 | + | * Status: Implemented (in PHP 7.4) |
- | * Discussion: https:// | + | * Discussion: https:// |
- | * Status: Draft | + | * Target version: PHP 7.4 |
+ | * Implementation: | ||
===== Introduction ===== | ===== Introduction ===== | ||
The human eye is not optimized for quickly parsing long sequences of | The human eye is not optimized for quickly parsing long sequences of | ||
- | digits. Thus, a lack of visual separators | + | digits. Thus, a lack of visual separators |
- | to read and debug code, and can lead to unintended mistakes. | + | read and debug code, and can lead to unintended mistakes. |
<code php> | <code php> | ||
Line 24: | Line 24: | ||
<code php> | <code php> | ||
- | $discount = 12300; // Is this 12,300? Or 123, because it's in cents? | + | $discount = 13500; // Is this 13,500? Or 135, because it's in cents? |
</ | </ | ||
Line 33: | Line 33: | ||
<code php> | <code php> | ||
- | $threshold = 1_000_000_000; | + | $threshold = 1_000_000_000; |
- | $testAmt | + | $testValue |
- | $discount = 123_00; | + | $discount = 135_00; // $135, stored as cents |
</ | </ | ||
Line 45: | Line 45: | ||
299_792_458; | 299_792_458; | ||
0xCAFE_F00D; | 0xCAFE_F00D; | ||
- | 0b0010_1101; // binary | + | 0b0101_1111; // binary |
- | 026_73_43; | + | 0137_041; // octal |
</ | </ | ||
Line 58: | Line 58: | ||
_100; // already a valid constant name | _100; // already a valid constant name | ||
- | // these all produce "Parse error: syntax error" | + | // these all produce "Parse error: syntax error": |
100_; // trailing | 100_; // trailing | ||
1__1; // next to underscore | 1__1; // next to underscore | ||
Line 67: | Line 67: | ||
</ | </ | ||
- | ===== Use cases ===== | + | ===== Unaffected PHP Functionality |
- | Business logic thresholds, scientific constants, and unit test values | + | Adding an underscore between digits in a numeric literal will not |
- | are common situations where large numeric literals are necessary. | + | change its value. The underscores |
+ | stage, so the runtime is not affected. | ||
- | ==== Use cases to avoid ==== | + | <code php> |
+ | var_dump(1_000_000); | ||
+ | </ | ||
- | It may be tempting | + | This RFC does not change the behavior of string |
- | credit card, and social security numbers since these values appear | + | conversion. Numeric separators are intended to improve code |
- | numeric. However, this is almost always a bad idea, since these | + | readability, not alter how input is processed. |
- | values often have prefixes and leading digits that are significant. | + | |
- | A good rule of thumb is that if it doesn' | + | ===== Backward Incompatible Changes ===== |
- | mathematical operators on a value (e.g. adding it, multiplying it, | + | |
- | dividing it, etc.), then an integer probably isn' | + | None. |
- | store it. | + | |
+ | ===== Discussion ===== | ||
+ | |||
+ | ==== Use cases ==== | ||
+ | |||
+ | Digit separators | ||
+ | [[https:// | ||
+ | accurately and confidently " | ||
+ | rather than having to count them. This measurably lessens | ||
+ | to correctly read numbers longer than four digits. | ||
+ | |||
+ | Large numeric literals are commonly used for business logic | ||
+ | constants, unit test values, and performing data conversions. | ||
+ | For example: | ||
+ | |||
+ | Composer' | ||
<code php> | <code php> | ||
- | // never do this: | + | usleep(350000); |
- | $phoneNumber = 345_6789; | + | |
- | $creditCard = 378_2822_4631_0005; | + | usleep(350_000); // with separator |
- | $socialSecurity = 111_11_1111; | + | |
</ | </ | ||
- | ===== Backward Incompatible Changes ===== | + | Conversion of an Active Directory timestamp (the number of |
+ | 100-nanosecond intervals since January 1, 1601) to a Unix timestamp: | ||
- | None. | + | <code php> |
+ | $time = (int) ($adTime / 10000000 - 11644473600); | ||
- | ===== Unaffected PHP Functionality ===== | + | $time = (int) ($adTime / 10_000_000 - 11_644_473_600); |
+ | </ | ||
- | Underscores in numeric literals will be stripped out during the | + | Working with scientific constants: |
- | lexing stage, so the runtime will not be affected. | + | |
<code php> | <code php> | ||
- | var_dump(1_000_000); // int(1000000) | + | const ASTRONOMICAL_UNIT = 149597870700; // without separator |
+ | |||
+ | const ASTRONOMICAL_UNIT = 149_597_870_700; | ||
</ | </ | ||
- | This RFC does not change the behavior of string | + | Separating bytes in a binary or hex literal: |
- | conversion. Numeric separators | + | |
- | readability, not alter how input is processed. | + | <code php> |
+ | 0b01010100011010000110010101101111; | ||
+ | |||
+ | 0b01010100_01101000_01100101_01101111; | ||
+ | |||
+ | 0x42726F776E; | ||
+ | |||
+ | 0x42_72_6F_77_6E; | ||
+ | </ | ||
+ | |||
+ | ==== Use cases to avoid ==== | ||
+ | |||
+ | It may be tempting to use integers for storing data such as phone, | ||
+ | credit card, and social security numbers since these values appear | ||
+ | numeric. However, this is almost always a bad idea, since such | ||
+ | numbers often have prefixes and leading digits that are significant. | ||
+ | |||
+ | A good rule of thumb is that if it doesn' | ||
+ | mathematical operators on a value (e.g. adding it, multiplying it, | ||
+ | etc.), then an integer probably isn't the best way to store it. | ||
+ | |||
+ | <code php> | ||
+ | // don't do this: | ||
+ | $phoneNumber = 345_6789; | ||
+ | $creditCard = 231_6547_9081_2543; | ||
+ | $socialSecurity = 111_11_1111; | ||
+ | </ | ||
- | ===== Will it be harder to search for numbers? | + | ==== Will it be harder to search for numbers? ==== |
A concern that has been raised is whether numeric literal separators | A concern that has been raised is whether numeric literal separators | ||
Line 118: | Line 164: | ||
practice, this isn't problematic as long as a codebase is consistent. | practice, this isn't problematic as long as a codebase is consistent. | ||
- | ===== Prior art ===== | + | Furthermore, |
+ | To use an earlier example, 13_500 and 135_00 could be differentiated | ||
+ | in a find/ | ||
+ | literal, which allows searching for a value like " | ||
+ | the numbers containing that specific byte. | ||
- | Numeric literal separators are widely supported in other programming languages. | + | ==== Should it be the role of an IDE to group digits? ==== |
- | * Ada: single, between digits [[http:// | + | It has been suggested that numeric literal separators aren't needed |
- | * C# (proposal | + | for better readability, since IDEs could be updated to automatically |
- | * C++: single, between digits (single quote used as separator) [[http:// | + | display large numbers |
- | * Java: multiple, between digits [[https:// | + | |
- | * JavaScript and TypeScript: single, between digits [[http:// | + | |
- | * Julia: single, between digits [[https:// | + | |
- | * Perl: single, between | + | |
- | * Python: single, between digits [[https:// | + | |
- | * Ruby: single, between digits [[http:// | + | |
- | * Rust: multiple, anywhere [[https:// | + | |
- | * Swift: multiple, between digits [[https:// | + | |
- | ===== Proposed Voting Choices ===== | + | However, it isn't always desirable to group numbers the same way. |
+ | For example, a programmer may write '' | ||
+ | depending on whether or not it represents a financial quantity stored | ||
+ | as cents: | ||
- | Add numeric literal separators in PHP 7.4? Yes/No. | + | <code php> |
+ | $total = 100_500_00; // represents $100,500.00 stored as cents | ||
- | ===== Patches and Tests ===== | + | $total |
+ | </ | ||
- | Pending... | + | Binary and hex literals may also be grouped by a varying number of |
+ | digits to reflect how they are used (e.g. bits may be separated into | ||
+ | nibbles, bytes, or words). An IDE cannot do this automatically | ||
+ | without knowing the programmer' | ||
- | ===== Why resurrect this proposal? | + | ==== Why resurrect this proposal? ==== |
The [[https:// | The [[https:// | ||
Line 157: | Line 207: | ||
JavaScript, and TypeScript), | JavaScript, and TypeScript), | ||
feature than was made before. | feature than was made before. | ||
+ | |||
+ | ==== Should I vote for this feature? ==== | ||
+ | |||
+ | Andrea Faulds summarized the considerations [[https:// | ||
+ | |||
+ | < | ||
+ | This feature offers some benefit in some cases. It doesn' | ||
+ | much new complexity. There' | ||
+ | the form of the existing number tokens. It fits in well [with] what's | ||
+ | already there, consistently applying to all number literals. It follows | ||
+ | established convention in other languages. Its appearance at least hints | ||
+ | that values with these separators are not constants or identifiers, | ||
+ | numbers, reducing potential for confusion. It limits its own application | ||
+ | to prevent abuse (no leading, trailing, or repeated separators). And | ||
+ | it's relatively intuitive. | ||
+ | </ | ||
+ | |||
+ | ==== Comparison to other languages ==== | ||
+ | |||
+ | Numeric literal separators are widely supported in other programming languages. | ||
+ | |||
+ | * Ada: single, between digits [[http:// | ||
+ | * C#: multiple, between digits [[https:// | ||
+ | * C++: single, between digits (single quote used as separator) [[http:// | ||
+ | * Java: multiple, between digits [[https:// | ||
+ | * JavaScript and TypeScript: single, between digits [[https:// | ||
+ | * Julia: single, between digits [[https:// | ||
+ | * Kotlin: multiple, between digits [[https:// | ||
+ | * Perl: single, between digits [[https:// | ||
+ | * Python: single, between digits [[https:// | ||
+ | * Ruby: single, between digits [[http:// | ||
+ | * Rust: multiple, anywhere [[https:// | ||
+ | * Swift: multiple, between digits [[https:// | ||
+ | |||
+ | ===== Vote ===== | ||
+ | |||
+ | Voting started 2019-05-30 and ended 2019-06-13. | ||
+ | |||
+ | <doodle title=" | ||
+ | * Yes | ||
+ | * No | ||
+ | </ | ||
===== References ===== | ===== References ===== | ||
+ | |||
+ | Request to revive RFC: https:// | ||
Discussion from previous RFC: https:// | Discussion from previous RFC: https:// | ||
- | Previous | + | Blog post about original |
rfc/numeric_literal_separator.1556665290.txt.gz · Last modified: 2019/04/30 23:01 by theodorejb