Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:75668 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 79262 invoked from network); 17 Jul 2014 12:49:38 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 17 Jul 2014 12:49:38 -0000 Authentication-Results: pb1.pair.com header.from=thomas@nunninger.info; sender-id=unknown Authentication-Results: pb1.pair.com smtp.mail=thomas@nunninger.info; spf=permerror; sender-id=unknown Received-SPF: error (pb1.pair.com: domain nunninger.info from 87.106.55.207 cause and error) X-PHP-List-Original-Sender: thomas@nunninger.info X-Host-Fingerprint: 87.106.55.207 mail.nunninger.info Linux 2.6 Received: from [87.106.55.207] ([87.106.55.207:33115] helo=mail.nunninger.info) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id 4F/E1-00245-C56C7C35 for ; Thu, 17 Jul 2014 08:49:33 -0400 Received: from pd95c6425.dip0.t-ipconnect.de ([217.92.100.37] helo=[192.168.178.30]) by mail.nunninger.info with esmtpsa (TLS1.0:DHE_RSA_AES_128_CBC_SHA1:16) (Exim 4.69) (envelope-from ) id 1X7l2g-0000pD-Js; Thu, 17 Jul 2014 12:44:19 +0000 Message-ID: <53C7C50A.6030601@nunninger.info> Date: Thu, 17 Jul 2014 14:43:54 +0200 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Thunderbird/24.6.0 MIME-Version: 1.0 To: Dan Ackroyd CC: Andrea Faulds , Zeev Suraski , Stas Malyshev , Andrey Andreev , Rowan Collins , "internals@lists.php.net" References: <08503591-EFC8-48E6-984E-FFC292C5EA5F@ajf.me> <16D48604-0C0A-4613-91A4-21392E3A2636@ajf.me> <05CE2216-C5D9-4937-9F2E-AA1407284D9F@ajf.me> <53C460DF.5040304@sugarcrm.com> <53C53A96.2040303@gmail.com> <53C55342.1010207@sugarcrm.com> <53C563B3.6060905@gmail.com> <54536191-1B92-4933-973F-0C8289D13A4C@ajf.me> <00d12255efc53466245b21a83ff7d474@mail.gmail.com> <1CE2ACC0-D6CA-407B-99C7-4914311B733E@ajf.me> <53C6CFB7.8090908@sugarcrm.com> <118BB3D7-BE52-44AB-BD0E-942830D44A2A@ajf.me> <9B7B8559-61FE-493D-BAEE-53E8C84D5E91@ajf.me> <53C795EA.1070303@nunninger.info> In-Reply-To: Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 8bit X-Spam-Score: -1.3 (-) X-Spam-Several-Recipients: Yes Subject: Re: [PHP-DEV] [RFC] Scalar Type Hinting With Casts (re-opening) From: thomas@nunninger.info (Thomas Nunninger) Hi Dan, On 07/17/2014 02:12 PM, Dan Ackroyd wrote: > Thomas Nunninger wrote: >> - "scalar parameter casting" should just be a convenience for coding: >> >> function foo( (int) $i, (string) $s ) >> { >> } >> >> is the same as: >> >> function foo( $i, $s ) >> { >> $i = (int) $i; >> $s = (string) $s; >> } >> >> or perhaps better:: >> >> $i = (int) $i; >> $s = (string) $s; >> >> foo( $i, $s ); >> >> >> That way you decide if you want to be very strict about the data in your >> variables or not, and both parties (strict vs. non-strict) can share code: > > I agree generally with your mail apart from this bit - people don't > always just call code directly and so can't tell what types parameters > should be. > > When you're calling code dynamically, e.g. through a dependency > injection container, you need to be able to inspect what types are > expected from outside the function. > > e.g. > > $dic->execute( > 'foo', > [ > 'i' => $request->getParam('i'), > 's' => $request->getParam('s') > ] > ); > > Without having the type-hinting/casting information available in the > function, it's not possible for the calling code to know what type the > function is expecting, and so it isn't able to cast it to what the > function is expecting. Perhaps I miss your point. But what is the difference to current behavior if you do not know about the types? With casting the calling code does not need to know how to cast as the called code accepts the parameter if the value can be used without data loss. (If the example was misleading because the cast is happening before calling the function: This should only stress, that providing usable data is not a responsibility of the called function but the calling code.) If the called function is strict it checks the input parameters in the function and raises some kind of error if information is lost on casting (not if the type is wrong). If information is lost, E_CAST is raised and PHP would use type juggling with expected or unexpected result (e.g. non-numeric strings casted to int). The difference to current behavior is that the product owner can decide if he wants strict behavior or not. Or is your point about inspection of parameter type? Why shouldn't reflection be able to provide information about scalar parameter casting? Regards Thomas > On 17 July 2014 10:22, Thomas Nunninger wrote: >> Hi, >> >> On 07/16/2014 10:45 PM, Andrea Faulds wrote: >>> >>> >>> On 16 Jul 2014, at 21:43, Zeev Suraski wrote: >>> >>>>> anything this RFC permits will >>>>> be permitted by zpp, it's the reverse that isn't necessarily true. >>>> >>>> >>>> Right, so it needs to be fixed. It makes no sense to force a new agenda >>>> on the language that's inconsistent with the rest of the language. Align >>>> your new feature to the rest of the language, not the other way around. >>> >>> >>> But to do so would be to make the feature less useful, nor satisfy people >>> who want stricter hinting. >> >> >> tl;dr: >> >> - I'd like to have E_CAST on all castings/type jugglings even if we do not >> get scalar type hinting. >> >> - I propose to say/implement "scalar parameter casting" instead of "scalar >> type hinting" with a casting syntax: >> >> function foo( (int) $i, ...) >> >> That way we lower expectations, explain the different syntax/semantics in >> contrast to hints, give a hint what scalar parameter casting does, and I see >> the use-cases of both parties fulfilled. >> >> ------- >> >> I didn't follow the complete thread in detail. And I have to confess that >> I'm a big fan of strictly "defining types of parameters", because I see how >> it could help me in my work. >> >> BUT: As I see it, E_CAST (with the existing type juggling rules/casts) plus >> "scalar parameter casting" is the best compromise in the spirit/history of >> PHP without BC breaks and I think all use-cases are satisfied: >> >> >> - E_CAST notifies me about data loss on type juggling. >> >> - "scalar parameter casting" should just be a convenience for coding: >> >> function foo( (int) $i, (string) $s ) >> { >> } >> >> is the same as: >> >> function foo( $i, $s ) >> { >> $i = (int) $i; >> $s = (string) $s; >> } >> >> or perhaps better:: >> >> $i = (int) $i; >> $s = (string) $s; >> >> foo( $i, $s ); >> >> >> That way you decide if you want to be very strict about the data in your >> variables or not, and both parties (strict vs. non-strict) can share code: >> >> >> - With E_CAST you get additional information on data loss on type juggling >> and casting in your complete code base. That's a plus for everybody who's a >> little bit scary about type juggling in those cases. >> >> - As a fan of strict mode I can develop my applications and libraries in >> E_CAST mode via an error handler that throws exceptions on E_CAST. (We even >> run our code with E_ALL in production to find edge cases.) >> >> - I see the severity of E_CAST on a level like E_NOTICE and E_STRICT: Best >> practice - if others do not understand/care it's their "problem" but they >> can use my code like each other code. >> >> - As a fan of non-strict behavior, you can provide a string for a parameter >> that is defined to be an integer. If it contains a number you are happy that >> my code works as PHP deals with casting. If your string does not contain a >> usable value you have to live with the good old PHP way when you use code >> with wrong input data and my code treats it as an integer and you perhaps >> have some data loss. But that's not the responsibility of my code - >> especially if I interpret the casting syntax as casting the parameters >> before hitting my method/function. (BTW: I don't think that casting should >> be used as sanitizing of user input like it was proposed/said to be widely >> used. I prefer validation over sanitizing.) >> >> - Depending where and how I define my error handler, I do not see that my >> code needs to behave differently if E_CAST is enabled or not. I think you >> should implement your error_handler for E_CAST in the spirit of Symfony's >> debug mode: In debug mode all errors are converted to exceptions but they >> are ignored in production mode. I guess you'd never say: My application >> behaves differently. Otherwise you probably use exceptions for control flow. >> (I do not say that you have to disable E_CAST for your production mode. But >> if your code passes all tests in E_CAST, there is a good chance that it >> works without E_CAST as well. Then it's your decision as product owner if >> you have to break on errors in edge cases or not.) >> >> - Regarding consistency to array and object hints: Using the casting >> syntax/semantics you could even provide (array) and (object) as "scalar >> parameter casting" in contrast to the hints. But of course you can argue >> that users are confused about "(array)" vs. "array". I could live with that >> confusion as people have to learn about "parameter casting" and that should >> be explicitly mentioned in the docs/tutorials/blog posts/... >> >> - I don't know if there is a downside for static code analysis. But probably >> you even need defined return types for that. >> >> >> Regards >> >> Thomas >> >> >> -- >> PHP Internals - PHP Runtime Development Mailing List >> To unsubscribe, visit: http://www.php.net/unsub.php >> > -- Dipl.-Inf. Thomas Nunninger Kartäuserstraße 3 D-79102 Freiburg i. Br. Tel: +49 761 2171508-0 Mobil: +49 163 7115153 http://nunninger.info USt-IdNr: DE259832548