On Oct 20 2014, at 8:07 PM, Josh Watzman <jwatz...@fb.com> wrote:

> I think this is pretty cool, but I'm really worried about some of its typing 
> implications. In particular:
>
>> The functions return FALSE on failure instead of NULL because:
>
> Throwing an exception or even returning NULL seems so much better than 
> returning "false" -- "false" is a boolean, not an error, and despite some 
> historical cases of PHP using "false" as a poor person's error code, it 
> really isn't. If you want error codes, use error codes, or use exceptions, 
> but having two kinds of failure, null vs false, is really confusing.
>
> Addressing your arguments one by one:
>
>>      • If strict type hinting were added, they would fail for a nullable 
>> typehint
>
> Throwing an exception also addresses this, in a much cleaner way. If you're 
> worried about strict typing, then returning "false" is even worse, since the 
> return type of, for example, to_int is now "int | bool" as opposed to 
> "nullable-int" or "int" (if you throw).
>
>>      • FALSE is a traditional error value in PHP
>
> Since this is a new function, one that doesn't interoperate in any 
> complicated way with the existing library or affect BC, this doesn't seem 
> that important. IMO a language should have one failure/absense-of-value, in 
> most cases "null", and having a weird second case seems, well, weird. If you 
> have more interesting failure cases, just throw an exception, or return null 
> if you want, don't continue propagating a weird second kind of null (that 
> isn't actually null, it's a boolean false).
>
> Also, that we *couldn't* introduce a meaningful to_bool function, even if we 
> decided we wanted it, indicates to me that returning false is the wrong thing 
> to do.
>
>>      • NULL is used to signify the absence of a value - but what we want to 
>> signify is an invalid value (similar to 0 vs NaN)
>
> I might argue that failure is indeed absense-of-value, but an exception seems 
> like a much better way to convey this.
>
> It's also interesting to look at how other languages handle failures of this 
> kind. Most imperative languages I know of either throw or return null; in 
> particular, Python, which has fairly similar type system to PHP in a lot of 
> ways, throws. Functional languages do more interesting things; Haskell does 
> something complicated but morally equivalent to returning null. But I'm not 
> aware of any language which specifically returns false.


I'm going to second Josh on this and add some of my own thoughts as a userland 
developer.

I believe it is important to have a simple, safe, and consistent way to cast 
values in PHP, and I would be supportive of these functions regardless of 
whether they throw an exception or return an error value. With that said, I 
believe that exceptions would be the best way to handle cast failures for the 
following reasons:

1. Exceptions can provide more information about the cast failure (e.g. 
overflow vs. invalid type vs. missing `__toString` method)
2. Throwing an exception is safer. For example, `strpos($haystack, $needle, 
to_int($offset))` would thrown an exception rather than silently converting 
$offset to 0 if it can't be safely cast.
3. There *is* precedent for this in other languages. Josh already mentioned 
Python, and I'll add C#. `Convert.ToInt64()` in C# throws a `FormatException` 
if the string does not have valid syntax, or an `OverflowException` if the 
value is less than Int64.MinValue or greater than Int64.MaxValue.
4. Mixed return types are a bad pattern. If we get scalar return type 
declarations in the future it would be nice to be able to use them with these 
functions.

On Oct 20 2014, at 8:17 PM, Andrea Faulds <a...@ajf.me> wrote:
> Exceptions make chaining more difficult.

How so? Chaining is worse with error values, in my experience! For example:

    $result = do_something_with(to_int(to_float($value)));
    if ($result === false) {
        // I have no idea which function returned false or why
    }

vs.

    try {
        do_something_with(to_int(to_float($value)));
    } catch (Exception $e) {
        // I know exactly which function caused the error and why it occurred
    }

My userland polyfill includes a branch which throws exceptions: 
https://github.com/theodorejb/PolyCast/tree/use-exceptions.

Theodore Brown
http://theodorejb.me

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

Reply via email to