Skip to content

Commit b0d0d37

Browse files
committed
Initial writing of PPC to define equ
1 parent f22f090 commit b0d0d37

File tree

1 file changed

+118
-0
lines changed

1 file changed

+118
-0
lines changed

ppcs/ppcTODO-undef-aware-equality.md

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
# `undef`-aware Equality Operators
2+
3+
## Preamble
4+
5+
Author: Paul Evans <PEVANS>
6+
Sponsor:
7+
ID: TODO
8+
Status: Exploratory
9+
10+
## Abstract
11+
12+
Adds new infix comparison operators that are aware of the special nature of the `undef` value, comparing it as distinct from the number zero or the empty string.
13+
14+
## Motivation
15+
16+
Perl has two sets of comparison operators; one set that considers the stringy nature of values, and another that considers numerical values. When comparing against `undef`, the stringy operators treat undef as an empty string, and the numerical operators treat it as zero. In both cases, a warning is produced:
17+
18+
```
19+
Use of uninitialized value in string eq at ...
20+
```
21+
22+
Sometimes it is useful to consider that `undef` is in fact a different value, distinct from any defined string or number - even empty or zero. Currently in Perl, to check if a given value (which may be `undef`) is equal to a given string value, the test must make sure to check for definedness:
23+
24+
```perl
25+
if( defined $x and $x eq $y ) { ... }
26+
```
27+
28+
Furthermore, if the value `$y` can also be undefined, it may be desired that in that case it matches if `$x` is also undefined. In that situation, the two cases must be considered individually:
29+
30+
```perl
31+
if( (!defined $x and !defined $y) or
32+
(defined $x and defined $y and $x eq $y) ) { ... }
33+
```
34+
35+
Countless bugs across countless modules have been caused by failing to check in such a way and using code such as simply `$x eq $y` in these circumstance.
36+
37+
By providing new comparison operators that have different behaviour with undefined values, Perl can provide more convenient choice of behaviours for authors to use.
38+
39+
## Rationale
40+
41+
(explain why the (following) proposed solution will solve it)
42+
43+
## Specification
44+
45+
A new operator, named `equ`, which has the same syntax as regular string equality `eq`, but semantics identical to that given above:
46+
47+
```perl
48+
$x equ $y
49+
50+
# Equivalent to (!defined $x and !defined $y) or
51+
# (defined $x and defined $y and $x eq $y)
52+
```
53+
54+
In particular, given two `undef` values, this operator will yield true. Given one `undef` and one defined value, it yields false, or given two defined values it will yield the same answer that `eq` would. In no circumstance will it provoke a warning of undefined values.
55+
56+
Likewise, a new operator named `===`, which provides the numerical counterpart:
57+
58+
```perl
59+
$x === $y
60+
61+
# Equivalent to (!defined $x and !defined $y) or
62+
# (defined $x and defined $y and $x == $y)
63+
```
64+
65+
Note that while the `===` operator will not provoke warnings about undefined values, it could still warn about strings that do not look like numbers.
66+
67+
## Backwards Compatibility
68+
69+
As these infix operators are currently syntax errors in existing versions of Perl, it is not required that they be feature-guarded.
70+
71+
However, it may still be considered useful to add a feature guard in order to provide some compatibility with existing code which uses the `Syntax::Operator::Equ` CPAN module. Likely this would be named `equ`:
72+
73+
```perl
74+
use feature 'equ';
75+
```
76+
77+
Once the feature becomes stable it is likely this would be included in an appropriate `use VERSION` bundle, so users would not be expected to request it specifically in the long-term.
78+
79+
## Security Implications
80+
81+
No new issues are anticipated.
82+
83+
## Examples
84+
85+
## Prototype Implementation
86+
87+
This operator is already implemented using the pluggable infix operator support of Perl version 5.38, in CPAN module [`Syntax::Operator::Equ`](https://metacpan.org/pod/Syntax::Operator::Equ).
88+
89+
## Future Scope
90+
91+
Considering further the possible idea to provide a `match/case` syntax inspired by [`Syntax::Keyword::Match`](https://metacpan.org/pod/Syntax::Keyword::Match), this operator would be a useful addition in combination with that as well, allowing dispatch on a set of fixed values as well as `undef`:
92+
93+
```perl
94+
match( $x : equ ) {
95+
case(undef) { say "The value in x is undefined" }
96+
case("") { say "The value in x is empty string" }
97+
case("ABC") { say "The value in x is ABC" }
98+
...
99+
}
100+
```
101+
102+
## Rejected Ideas
103+
104+
* It is not possible to unambiguously provide extensions of the ordering operators `cmp` and `<=>` in a similar way, because this requires a decision to be made as to the sorting order of undefined values, compared to any defined string or number. While it may be natural to consider that undef sorts before an empty string, there is no clear choice on where undef would sort compared to (signed) numbers. Would it be before any number, even negative infinity? This would place it far away from zero.
105+
106+
* Likewise, because it is not possible to provide an undef-aware version of `cmp` or `<=>`, the ordering comparison operators of `le`, `lt` and so on are also not provided.
107+
108+
## Open Issues
109+
110+
* Should we also provide negated versions of these operators? While much rarer in practice, it may be useful to provide a "not equ", perhaps spelled `nequ` or `neu`; and likewise `!===` or `!==` for the numerical version. These do not suffer the sorting order problem outlined above for more general comparisons.
111+
112+
* As an entirely alternate proposal, should we instead find ways to apply behaviour-modifying flags to the existing operators? That is, rather than adding a new `equ` and `===` could we instead consider some syntax such as `eq:u` and `==:u` as a modifier flag, similar to the flags on regexp patterns, as a way to modify operators? This would be extensible in a more general way to more operators, while also allowing more flexible flags in future, such as for instance a case-ignoring string comparison to be spelled `eq:i`. This alternate proposal may be the subject of an alternate PPC document.
113+
114+
## Copyright
115+
116+
Copyright (C) 2024, Paul Evans.
117+
118+
This document and code and documentation within it may be used, redistributed and/or modified under the same terms as Perl itself.

0 commit comments

Comments
 (0)