Re: [RFC] Scalar Type Hinting With Casts (re-opening)
| From: | Chris Wright | Date: | Mon, 14 Jul 2014 13:33:04 +0000 |
| Subject: | Re: [RFC] Scalar Type Hinting With Casts (re-opening) | ||
| References: | 1 2 | Groups: | php.internals |
| Request: | Send a blank email to internals+get-75457@lists.php.net to get a copy of this message | ||
On 14 July 2014 13:58, Andrea Faulds <ajf@ajf.me> wrote:
> Hello again,
>
> One of the issues with the RFC as it stands is how to handle bool casting.. While int, float
> and string only allow lossless casting (with the exception of objects, but we can’t really do
> anything about that), bool’s behaviour at the moment is quite different. I don’t think it makes
> sense so I won’t discuss the current behaviour, only possible new ones.
>
> One option is simply to forget about being lossless and make the bool type hint accept any
> value, meaning any truthy value or any falsey value would yield what is expected without error. This
> would ensure that if some stupid programmer (like myself ;) has passed in a non-boolean
> truthy/falsey value to your function, it’ll be handled correctly. It would mean all your bit hacks
> ($foo & FLAG etc.) would work, anything you got from $_GET (e..g. ?foobar=1). However, this is
> unlikely to catch bugs in code, because literally any PHP value would work. For that reason, I’m
> not sure this is the way forward.
>
> Another option is go completely strict and allow only boolean values, failing everything else.
> This would be unlike the int, float and string hints, which are flexible and cast, but would be more
> helpful for catching bugs. However, not casting at all isn’t very “PHP-like”, and forcing
> people to manually cast with (bool) might not be ideal. If we were to go for this one, I might also
> accept objects casting to bool (which the default handler does), because I don’t want to stop
> extension developers from making bool-like objects if they so please.
>
> The final option I’m thinking about is a limited set of values. TRUE, FALSE and NULL would be
> accepted, along with the integer and float values 1 and 0 (which are the int/float TRUE and FALSE
> cast to, respectively), ‘1’ and the empty string (which are the string values TRUE and FALSE
> cast to), and ‘0’ (which (string)(int)FALSE would give you), along with objects casting to
> boolean. It’s not a perfect solution, but I currently feel that this is the most sensible option
> bar going for full strictness.
>
> I’m not really decided, however. Every time I try to think about this, I usually end up going
> in circles. Anthony doesn’t seem to be decided either. Hence I’m putting this up for discussion.
>
> What are your thoughts?
>
> --
> Andrea Faulds
> http://ajf.me/
I've already said this in IRC but summing up for the benefit of everyone else:
1) We already have a place where there is an implicit boolean cast,
namely if ($var). Personally I would find it somewhat
counter-intuitive if a parameter declared as bool didn't behave the
same way.
2) A common-ish use case here would be:
function foo(bool $bool) {}
foo($flags & A_FLAG);
The intent of the expression $flags & A_FLAG is obvious to the reader
as fetching a boolean, but the result will often be an integer that is
neither 1 nor 0. This cannot be handled by foo((bool)$flags & A_FLAG);
because of precedence, foo((bool)($flags & A_FLAG)); is messy. Andrea
suggested foo($flags & A_FLAG != 0); which is better but still a
little messy.
Personally I would rather just accept data loss and stay consistent
with the rest of the language (i.e. condition evaluation), but I do
understand the PoV of those resistant to it.