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]

Reply via email to