Skip to content

Commit ed15447

Browse files
garurjbs
authored andcommitted
update optional chaining RFC 0018
* typo fix on example code; * fix paragraph that approaches CPAN emulation of the feature; * move mention of optional chains in string interpolation / regexes from "Open Issues" to "Future Scope", effectively addressing all open issues (and added nod to template literals);. * expand "rejected ideas" FAQ to include rationale over lexical pragmas and related ideas, while also deepening the explanation of why it should be explicit.
1 parent 4cd48a7 commit ed15447

File tree

1 file changed

+46
-16
lines changed

1 file changed

+46
-16
lines changed

rfcs/rfc0018.md

Lines changed: 46 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -114,9 +114,10 @@ those scenarios (but see 'Open Issues' below).
114114
Static tooling may confuse the new operator with a syntax error until
115115
updated.
116116

117-
Earlier versions of Perl could potentially emulate this feature with a CPAN
118-
module relying on something like XS::Parse::Infix (perl 5.14 onwards),
119-
though the implementation effort has not been explored.
117+
Because it is an infix operator with special/reserved characters and short-
118+
circuiting, this feature cannot be easily emulated as-is with a CPAN module.
119+
XS::Parse::Infix could help, but even that only works on a patched version of
120+
perl.
120121

121122
## Security Implications
122123

@@ -131,7 +132,7 @@ Expected common uses:
131132

132133
```perl
133134
# $val = defined $foo && defined $foo->{bar} ? $foo->{bar}[3] : ();
134-
$val = $foo?->{bar}?->[3};
135+
$val = $foo?->{bar}?->[3];
135136

136137
# $tmp = defined $obj ? $obj->m1 : (); $val = defined $tmp ? $tmp->m2 : ();
137138
$val = $obj?->m1?->m2;
@@ -225,6 +226,13 @@ The equivalence, in this case, would be:
225226
While this is the actual goal, a first version of the operator could ignore
226227
this and stick with named variables.
227228

229+
Also, optional chains under string interpolation and regular expressions
230+
could be enabled in the future, hidden behind a feature flag to prevent
231+
backwards compatibility issues, much like what was done with `postderef_qq`.
232+
However, due to the nature of the operator, the need for its usage on those
233+
contexts should not be too big - and even then it can be mitigated by efforts
234+
such as Template Literals (RFC0019).
235+
228236
## Rejected Ideas
229237

230238
The idea of a similar operator has been going on and off the p5p list since
@@ -238,6 +246,15 @@ arose in the past, and the design decisions that led to this particular RFC.
238246
Besides being shorter, the optional chain will NOT silence actual errors
239247
coming from a method, or from a defined value that is not a ref.
240248

249+
* Why not just a lexical pragma?
250+
251+
Providing the definedness check on arrow operators via a pragma is
252+
unfortunately not good enough as it (a) doesn't give you enough granularity
253+
and control of your chain in, say, `$o?->m1->m2?->m3;`; (b) promotes
254+
[action at a distance](https://en.wikipedia.org/wiki/Action_at_a_distance_(computer_programming));
255+
and (c) even if only enabled lexically, provides little to no gain in terms
256+
of reading/writing statements as `{no X; $o->m}` vs `$o->m if defined $o`.
257+
241258
* Why is the token `?->` and not "X"
242259

243260
There have been a lot of different proposals for this operator over the
@@ -266,9 +283,10 @@ issue of having to add a lot of repetitive and error-prone boilerplate tests
266283
on an entire chain individually, and nothing else.
267284

268285
While we could (hypothetically) try to expand this notion to other operators
269-
(e.g. `?=`, `?=~`, etc), the benefit of doing so is unclear at this point,
270-
and would require a lot of effort picking appart which operators should
271-
and shouldn't include the "optional" variation [4].
286+
(e.g. `?=`, `?=~`, etc) or even explore related ideas (such as a non-null
287+
assertion operator like `!->`), the benefit of doing so is unclear at this
288+
point, and would require a lot of effort picking appart which operators
289+
should and shouldn't include the "optional" variation [4].
272290

273291
* Why definedness and not truthfulness? Or 'ref'? Or 'isa'?
274292

@@ -280,13 +298,26 @@ treated as package/class names), so we cannot reliably test for 'ref'
280298
without making things really convoluted with assumptions, rules and
281299
exceptions for each type of data.
282300

283-
* Can we have implicit `?->` after its first use? Have it flip/flop against
284-
`->`?
301+
* Can we have implicit `?->` after its first use? Or have it flip/flop
302+
against `->` on a chain?
285303

286-
The idea is for `?->` to always be explicit, since it is testing the
287-
lefhand side of the expression. Making the operator change how explicit or
288-
implicit dereference works in the rest of the expression could lead to
289-
confusion and bugs.
304+
The proposed optional chain short-circuit is not a bugfix of the arrow
305+
dereference's behaviour, it's a shortcut to a common (and error prone)
306+
construct that happens when the developer wants to achieve just that. Short-
307+
circuiting instead of runtime exceptions could hide bugs, so we require
308+
developers to make a conscious and explicit choice every time they want this
309+
feature in any part of the chain. It may be a little bit tedious to
310+
write longer optional chains, but it will surely be easier to read,
311+
understand and spot logic errors if the operator is explicit.
312+
313+
This decision is endorsed by the fact that all implementations of the
314+
null-safe / optional chain operator in other languages also require it to be
315+
explicit. Besides, evidence suggests less than 20% of the usage will chain
316+
more than two calls[5].
317+
318+
A possible alternative to make the optional chain "greedy" could be the
319+
addition of yet another operator (like `??->`), but they are beyond the scope
320+
of this RFC and should be explored in another draft, if the need arises.
290321

291322
* Why not other identity values according to context? Like '' when
292323
concatenating strings, 0 on addition/subtraction and 1 on
@@ -302,9 +333,7 @@ the same results, e.g.: `"value is: " . ($ref?->{val} // '')`.
302333

303334
## Open Issues
304335

305-
Optional chains under string interpolation and regular expressions could be
306-
enabled in the future, hidden behind a feature flag to prevent backwards
307-
compatibility issues, much like what was done with `postderef_qq`.
336+
None.
308337

309338
## References:
310339

@@ -314,6 +343,7 @@ compatibility issues, much like what was done with `postderef_qq`.
314343
4. Python's proposal, and the ongoing discussion around it, are a noteworthy
315344
external example of the consequences of trying to add that logic to many
316345
different operators. https://peps.python.org/pep-0505
346+
5. https://github.com/alangpierce/coffeescript-soak-stats
317347

318348
## Copyright
319349

0 commit comments

Comments
 (0)