Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:78172 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 71639 invoked from network); 21 Oct 2014 02:59:44 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 21 Oct 2014 02:59:44 -0000 Authentication-Results: pb1.pair.com header.from=theodorejb@outlook.com; sender-id=pass Authentication-Results: pb1.pair.com smtp.mail=theodorejb@outlook.com; spf=pass; sender-id=pass Received-SPF: pass (pb1.pair.com: domain outlook.com designates 65.55.111.146 as permitted sender) X-PHP-List-Original-Sender: theodorejb@outlook.com X-Host-Fingerprint: 65.55.111.146 blu004-omc4s7.hotmail.com Received: from [65.55.111.146] ([65.55.111.146:53849] helo=BLU004-OMC4S7.hotmail.com) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id 5A/35-42514-B1CC5445 for ; Mon, 20 Oct 2014 22:59:40 -0400 Received: from BLU179-W5 ([65.55.111.136]) by BLU004-OMC4S7.hotmail.com over TLS secured channel with Microsoft SMTPSVC(7.5.7601.22751); Mon, 20 Oct 2014 19:59:37 -0700 X-TMN: [EhRZo/nS7oHn4umqWUIJqGvaZCN5ZLhx] X-Originating-Email: [theodorejb@outlook.com] Message-ID: To: Andrea Faulds , Josh Watzman CC: "internals@lists.php.net" Date: Mon, 20 Oct 2014 21:59:36 -0500 Importance: Normal Content-Type: text/plain; charset="Windows-1252" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 X-OriginalArrivalTime: 21 Oct 2014 02:59:37.0254 (UTC) FILETIME=[0CB9F460:01CFECDB] Subject: Re: [PHP-DEV] [RFC] Safe Casting Functions From: theodorejb@outlook.com (Theodore Brown) On Oct 20 2014=2C at 8:07 PM=2C Josh Watzman wrote:=0A= =0A= > I think this is pretty cool=2C but I'm really worried about some of its t= yping implications. In particular:=0A= >=0A= >> The functions return FALSE on failure instead of NULL because:=0A= >=0A= > Throwing an exception or even returning NULL seems so much better than re= turning "false" -- "false" is a boolean=2C not an error=2C and despite some= historical cases of PHP using "false" as a poor person's error code=2C it = really isn't. If you want error codes=2C use error codes=2C or use exceptio= ns=2C but having two kinds of failure=2C null vs false=2C is really confusi= ng.=0A= >=0A= > Addressing your arguments one by one:=0A= >=0A= >> =95 If strict type hinting were added=2C they would fail for a nullable= typehint=0A= >=0A= > Throwing an exception also addresses this=2C in a much cleaner way. If yo= u're worried about strict typing=2C then returning "false" is even worse=2C= since the return type of=2C for example=2C to_int is now "int | bool" as o= pposed to "nullable-int" or "int" (if you throw).=0A= >=0A= >> =95 FALSE is a traditional error value in PHP=0A= >=0A= > Since this is a new function=2C one that doesn't interoperate in any comp= licated way with the existing library or affect BC=2C this doesn't seem tha= t important. IMO a language should have one failure/absense-of-value=2C in = most cases "null"=2C and having a weird second case seems=2C well=2C weird.= If you have more interesting failure cases=2C just throw an exception=2C o= r return null if you want=2C don't continue propagating a weird second kind= of null (that isn't actually null=2C it's a boolean false).=0A= >=0A= > Also=2C that we *couldn't* introduce a meaningful to_bool function=2C eve= n if we decided we wanted it=2C indicates to me that returning false is the= wrong thing to do.=0A= >=0A= >> =95 NULL is used to signify the absence of a value - but what we want t= o signify is an invalid value (similar to 0 vs NaN)=0A= >=0A= > I might argue that failure is indeed absense-of-value=2C but an exception= seems like a much better way to convey this.=0A= >=0A= > It's also interesting to look at how other languages handle failures of t= his kind. Most imperative languages I know of either throw or return null= =3B in particular=2C Python=2C which has fairly similar type system to PHP = in a lot of ways=2C throws. Functional languages do more interesting things= =3B Haskell does something complicated but morally equivalent to returning = null. But I'm not aware of any language which specifically returns false.= =0A= =0A= =0A= I'm going to second Josh on this and add some of my own thoughts as a userl= and developer.=0A= =0A= I believe it is important to have a simple=2C safe=2C and consistent way to= cast values in PHP=2C and I would be supportive of these functions regardl= ess of whether they throw an exception or return an error value. With that = said=2C I believe that exceptions would be the best way to handle cast fail= ures for the following reasons:=0A= =0A= 1. Exceptions can provide more information about the cast failure (e.g. ove= rflow vs. invalid type vs. missing `__toString` method)=0A= 2. Throwing an exception is safer. For example=2C `strpos($haystack=2C $nee= dle=2C to_int($offset))` would thrown an exception rather than silently con= verting $offset to 0 if it can't be safely cast.=0A= 3. There *is* precedent for this in other languages. Josh already mentioned= Python=2C and I'll add C#. `Convert.ToInt64()` in C# throws a `FormatExcep= tion` if the string does not have valid syntax=2C or an `OverflowException`= if the value is less than Int64.MinValue or greater than Int64.MaxValue.= =0A= 4. Mixed return types are a bad pattern. If we get scalar return type decla= rations in the future it would be nice to be able to use them with these fu= nctions.=0A= =0A= On Oct 20 2014=2C at 8:17 PM=2C Andrea Faulds wrote:=0A= > Exceptions make chaining more difficult.=0A= =0A= How so? Chaining is worse with error values=2C in my experience! For exampl= e:=0A= =0A= =A0 =A0 $result =3D do_something_with(to_int(to_float($value)))=3B=0A= =A0 =A0 if ($result =3D=3D=3D false) {=0A= =A0 =A0 =A0 =A0 // I have no idea which function returned false or why=0A= =A0 =A0 }=0A= =0A= vs.=0A= =0A= =A0 =A0 try {=0A= =A0 =A0 =A0 =A0 do_something_with(to_int(to_float($value)))=3B=0A= =A0 =A0 } catch (Exception $e) {=0A= =A0 =A0 =A0 =A0 // I know exactly which function caused the error and why i= t occurred=0A= =A0 =A0 }=0A= =0A= My userland polyfill includes a branch which throws exceptions: https://git= hub.com/theodorejb/PolyCast/tree/use-exceptions.=0A= =0A= Theodore Brown=0A= http://theodorejb.me=0A= =0A= =