On Sun, Aug 25, 2024, at 17:31, Rowan Tommins [IMSoP] wrote: > On 25/08/2024 14:35, Larry Garfield wrote: >> My other concern is the list of supported expression types. I >> understand how the implementation would naturally make all of those >> syntactically valid, but it seems many of them, if not most, are >> semantically nonsensical. > > > I tend to agree with Larry and John that the list of operators should be > restricted - we can always allow more in future, but restricting later is > much harder. > > A few rules that seem logical to me: > > 1) The expression should be reasonably guaranteed to produce the same type as > the actual default. > > > - No casts > - No comparison operators, because they produce booleans from non-boolean > input > - No "<=>". Technically, it has an integer result, but it's rare to use it as > one, rather than a kind of three-value boolean > - No "instanceof" > - No "empty" > > 2) The expression should not have side effects (outside of exotic operator > overloads). > > > - No "include", "require", etc > - No "throw" > - No "print" > - Borderline, but I would also say no "clone" > > 3) The expression should be passing additional information into the function, > not pulling information out of it. The syntax shouldn't be a way to write > obfuscated reflection, or invert data flow from callee to caller. > > > - No assignments. > - No ternaries with "default" on the left-hand side - "$foo ? $bar : default" > is acting on local knowledge, but "default ? $foo : $bar" is acting on > information the caller shouldn't know > - Same for "?:" and "??" > - No "match" with "default" as the condition or branch, for the same reason. > "match($foo) { $bar => default }" is fine, match(default) { ... }" or > "match($foo) { default => ... }" are not. > > Note that these can be seen as aspects of the same rule: the aim of the > expression should be to transform the default value into another value of the > same type, not to pull it out and perform arbitrary operations based on it. > > > > I believe that leaves us with: > > > - Arithmetic operators: binary + - * / % **, unary + - > - Bitwise operators: & | ^ << >> ~ > - Boolean operators: && || and or xor ! > - Conditions with default on the RHS: $foo ? $bar : default, $foo ?: default, > $foo ?? default, match($foo) { $bar => default } > - Parentheses: (((default))) > > > > Even then, I look at that list and see more problems than use cases. As the > RFC points out, library authors already worry about the maintenance burden of > named argument support, will they now also need to question whether someone > is relying on "default + 1" having some specific effect? > > Maybe we should instead require justification for each addition: > > > - Bitwise | is nicely demonstrated in the RFC > - Bitwise & could probably be justified on similar grounds > - "$foo ? $bar : default" is discussed in the RFC > - The other "conditions with default on the RHS" in my shortlist above fit > the same basic use case > > Beyond that, I'm struggling to think of meaningful uses: "whatever the > function sets as its default, do the opposite"; "whatever number the function > sets as default, raise it to the power of 3"; etc. Again, they can easily be > added in later versions, if a use case is pointed out. > > > > Regards, > > -- > Rowan Tommins > [IMSoP]
Hi Rowan, you went through a lot of trouble to write this out, and the reasoning makes sense to me. However, all the nonsensical things you say shouldn’t be allowed are already perfectly allowed today, you just have to type a bunch of boilerplate reflection code. There is no new behavior here, just new syntax. — Rob