On Tue, Jun 25, 2019 at 3:10 PM Arnold Daniels <arnold.adaniels...@gmail.com>
wrote:

> Hi all,
>
> I would like to open the discussion for RFC: "Strict operators directive".
>
> This RFC proposes a new directive 'strict_operators'. When enabled,
> operators may cast operands to the expected type, but must comply to;
>
> * Typecasting is not based on the type of the other operand
>
> * Typecasting is not based on the value of any of the operands
> * Operators will throw a TypeError for unsupported types
>
> Reasoning; The current rules for type casting done by operators are
> inconsistent and complex, which can lead to surprising results where a
> statement seemingly contradicts itself.
>
> Using a directive means that backwards compatibility is guaranteed.
>
> https://wiki.php.net/rfc/strict_operators
>

Hi Arnold,

I like the idea behind this RFC. This is a good way to avoid unfortunate
legacy behavior without breaking BC. Here are some more detailed thoughts:

* I think to be really useful, this additionally needs
https://wiki.php.net/rfc/namespace_scoped_declares or some variation
thereof. Being able to say "this whole library uses strict operators" is
much more useful than specifying this in every file (and possibly missing
it somewhere and thus getting the wrong semantics). I will try to get a new
version of this RFC based on directories rather than namespaces into PHP 8.

* The sentence "In this case, we're passing an int to a function that
accepts float. The parameter is converted (widened) to float." should
probably not be referring to functions and parameters.

* "To compare two numeric strings as numbers, they need to be cast to
floats." This may loose precision for integers. It is better to cast to
numbers (int or float) using, with the canonical way being +$x. But I guess
that won't work under strict_operators. Maybe we should have a (number)
cast (it already exists internally...)

* This has already been mentioned by others: Having $str1 < $str2 perform a
strcmp() style comparison under strict_operators is surprising. I think
that overall the use of lexicographical string comparisons is quite rare
and should be performed using an explicit strcmp() call. More likely than
not, writing $str1 < $str2 is a bug and should generate a TypeError. Of
course, equality comparisons like $str1 == $str2 should still work, similar
to the distinction you make for arrays.

* If I understand correctly, under this RFC "foo" == 0 will throw a
TypeError, but ["foo"] == [0] will return false. Generally the behavior of
the recursive comparison here is that it's the same as strict == but all
errors become not-equal instead. Correct? I'm not sure how I feel about
this, as it seems to introduce one more set of semantics next to the weak
==, strict == and === semantics there already are.

* I also find it somewhat odd that you can't write something like "$obj !=
null" anymore, only "$obj !== null".

* I think the "solution" to the last three points is a) only support
numbers in relational operators (<,<=,>,>=,<=>) and throw TypeErrors
otherwise (maybe modulo provisions for object overloading) and b) allow
comparing any types in == and !=, without throwing a TypeError. The
question "Are 42 and 'foobar' equal?" has a pretty clear answer: "No they
aren't", so there is no need to make this a TypeError (while the question
"Is 42 larger than 'foobar'?" has no good answer.) I believe doing
something like this would roughly match how Python 3 works. (Edit: I see
now that this is mentioned in the FAQ, but I think it would be good to
reconsider this. It would solve most of my problems with this proposal.)

* String increment seems like a pretty niche use case, and I believe that
many people find the overflow behavior quite surprising. I think it may be
better to forbid string increment under strict_operators.

* A similar argument can be made for the use of &, | and ^ on strings.
While I have some personal fondness for these, in practical terms these are
rarely used and may be indicative of a bug. I think both for string
increment and string and/or/xor it may be better to expose these as
functions so their use is more explicit.

Regards,
Nikita

Reply via email to