Zeev,

> Actually there's a pretty simple way that's not strict type hints:
>
> 5) Add type hints using existing syntax, which are casts;  Change casts
> (both existing and these new ones) to emit a new E_CAST in case of data
> loss or 'bogus' conversions.

The issue with this, is that it changes how your calling code will
behave based on global configuration. Not an issue for the application
developer (since they can control the global config), but for a
library developer who makes reusable code, this is going to become a
nightmare to deal with.

Example:

    function foo(int $bar) {}
    foo("12abc"); // May silently succeed. May raise E_CAST error. May
throw exception. Who knows!

That sounds like it's not a big deal, but it will result in calling
code needing to get extra defensive to be robust:

    try {
        foo($something);
    } catch (\Exception) {
        // I have no idea what exception may have been thrown here
    }

Or ignoring the error entirely by "forcing" the unknown value to an integer:

    foo((int) $something);

Which is exactly what this RFC was designed to avoid. Explicit casts
can be lossy, because it's clear that the programmers intention is for
the loss to occur. So (bool) array(123) is a valid cast, because it's
explicit. But implicitly, it's really not clear if that's what was
intended or not.

IMHO, strict hints are dangerous in the context of PHP because PHP's
types can change in unpredictable ways. A variable that was an integer
can turn into a float through seemingly integer operations. Example:
$a / $b * $b will result in a float unless $b divides $a (even though
for sane values of $a and $b, it will be exactly representable as an
int).

And that also hints towards a benefit of adding a numeric hint as well
(which will accept (and cast to) either an int or a float, exactly how
is_numeric_string() does internally)... Which is something that may
want to be considered for this RFC.

That would again result in (int) casts being used, which would then
hide the *real* error cases, such as passing "apple" to a function
expecting an integer...

These cast rules differ from the existing cast rules for a very
significant and important reason: they are implicit. If the user wants
to force something, they still have the normal cast mechanism to do
that. These cast rules are designed so that reflexive (lossless) casts
are free ("12" is 12), but lossly casts need intervention by the user
to confirm intent.

The edges are where things get odd. "12abc" is currently accepted by
zpp int types, but raises a notice. That was why the RFC initially
included it as a notice. But I agree with the move to making it an
outright error.

But then you get problem areas like booleans. On one hand, "foo"
doesn't make sense, but on the other $flags & FLAG does. But that
could just as well be a string. So either we let everything satisfy a
boolean (how ZPP already works) or we restrict it to lossless casts,
or we make it strict. None of them are really overly good IMHO, but
it's something that should be discussed...

> I already mentioned before that I don't think consistency is a bad thing
> (and that's an understatement).  Having the syntax differ and have a
> separate, similar set of rules/behaviors is a disadvantage, not an
> advantage in my book.

Well, there is consistency. For the most part (around 95% of this
RFC), ZPP behaves the same way as this RFC is proposing. And I'd argue
that if this RFC is accepted, ZPP should be modified to behave like
this (for PHP_NEXT). The reason is that the rules for these implicit
casts are actually quite simple, with a few edge cases (which is where
the divergence from zpp happened).

> There are several advantages of adding this syntax with the simple casting
> behavior:
>
> 1. It saves a bit of code and improves readability for a *very* common use
> case.
> 2. It encourages developers to get the types straight instead of relying
> on implicit casts.

Implicit casts are good, when it's not clear what the programmer
intended. And simply passing a variable to a function doesn't indicate
intent as we don't have typed variables. So having implicit casts be
"safer" is a good thing, as there's always an explicit cast if they
need it. And if it's not clear, I'd prefer having the implicit cast
error, and let the programmer use an explicit cast to clarify intent.

My $0.02

Anthony

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to