Hi Thomas,

> Perhaps I miss your point. But what is the difference to current behavior if 
> you do not know about the types?

Not to the current behaviour, to the behaviour that would be possible
with scalar type-hinting.

>Or is your point about inspection of parameter type?  Why shouldn't reflection 
>be able to provide information about scalar parameter casting?

Yes, reflection should provide that information which makes the code:

>      function foo( $i, $s )
>      {
>        $i = (int) $i;
>        $s = (string) $s;
>      }


Not be equivalent to:

>      function foo( $i, $s )
>      {
>        $i = (int) $i;
>        $s = (string) $s;
>      }

My point is the reflection then allows the calling code to explicitly
cast the parameters to the type the function expects, _with_ data loss
if required, without triggering any warning on information loss. For
example:

function foo(bool $enabled) {...}

$enabledValue = $request->getParam('enabled');

$dic->execute('foo', ['enabled' => $enabledValue ] )

The DIC should be able to know that the function expects a bool and so
if the value of $enabledValue is the string 'true', that it should
convert it to the boolean true, and so make the function happy. So
that allows no E_CAST being generated, as there has been no implicit
cast, only an explicit conversion somewhere in the DIC.

cheers
Dan

On 17 July 2014 13:43, Thomas Nunninger <tho...@nunninger.info> wrote:
> 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 <tho...@nunninger.info> wrote:
>>>
>>> Hi,
>>>
>>> On 07/16/2014 10:45 PM, Andrea Faulds wrote:
>>>>
>>>>
>>>>
>>>> On 16 Jul 2014, at 21:43, Zeev Suraski <z...@zend.com> 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

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

Reply via email to