Matt,

>> And what about other languages that have exactly this behavior? Such
>> as Go/Hack/Haskell/etc. Do you see casts everywhere? No. You see them
>> where it needs to be explicit. Otherwise, people just write using the
>> correct types.
>>
>> And it also hand-waves over the fact that the same problem exists with
>> coercive types. You're going to get the error anyway if you try to
>> pass "apple" to an int parameter. So if someone was going to cast with
>> strict, they will cast with coercive.
>
> True. But you're also hand-waving over a point I brought up: many,
> many input sources for PHP return strings: HTTP calls, database calls,
> etc. With coercive mode, I can pass these values on to other function
> calls without a problem; with strict mode, I cannot; I MUST cast
> first.

Correct. Just like every other language that I mentioned.

> <snip>
>
>>> If I don't enable strict mode on my code, and somebody else turns on strict 
>>> when
>>> calling my code, there's the possibility of new errors if I do not perform
>>> validation or casting on such values. This means that the de facto standard 
>>> will
>>> likely be to code to strict (I can already envision the flood of PRs 
>>> against OSS
>>> projects for these issues).
>>
>> Incorrect. The only person that can turn on strict mode is you, the
>> author. Now someone can install your library, and edit it to turn on
>> strict mode (add the declares at the top of the file). But that's very
>> different from what strict proposes.
>
> Okay, I'm confused then.
>
> Let's consider this scenario:
>
> I have a library. It does _not_ declare strict. It _does_ make calls
> to either a web service or a database. Let's get even more specific:
> the code does _not_ define any _scalar_ type hints, but accepts a
> callable.
>
>     function execute(callable $callback)
>     {
>         // fetch some data from a web service or database,
>         // gather item1 and item 2 from it,
>         // and pass the data on to the callback, which was passed to us.
>         // Assume that we know that item1 is an int-like value, and
> item2 is a string-like value.
>         $callback($item1, $item2);
>     }
>
> You, as a consumer, declare your script in strict mode, and make a
> call to my own code.
>
>     declare(strict_types=1);
>     // somehow import the above function
>
>     $callback = function (int $item1, string $item2) {
>         // do something with the items...
>     };
>     execute($callback);
>
> How does that operate?
>
> https://wiki.php.net/rfc/scalar_type_hints_v5 indicates that the
> caller determines strict mode, but I'm unclear what the scope of that
> is: does it bubble down the entire stack? or does strict only apply to
> the specific calls made (i.e., before it reaches the function/method
> declared in the other file)? What happens when $callback is executed,
> and $item1 is '10'? Is it interpreted strictly, or weakly? Where is
> the boundary for where strict happens, exactly?
>
> If strict only applies to the execute() invocation, and doesn't apply
> to $callback or the calls made to the web service or database, then I
> can retract my statements; however, if the strict applies all the way
> down the stack from the caller, I can see definite issues. That's what
> I'm worried about.

It only applies to the `execute` call (which is no different from 5.x,
since there's no scalar types). But it does not apply to the
$callback($item1, $item2) call because the location of the *call* was
in a non-strict file. So the code you mentioned works 100%.

There is one gotcha here, which is that you can do the following:

<?php declare(strict_types=1);
function doStuff(callable $cb): int {
    $cb("test", "this");
}
?>
<?php // separate file

$cb = function(int $abc, string $def): int {};

$doStuff($cb);
?>

In that case, you'll get a type error inside of doStuff, because the
callback's call is incorrect. This is completely logical if you think
about it because you gave a type mismatch. This highlights a need for
typing of callables: function doStuff(callable(int, string):int $cb)
or something like that.


> <snip>
>
>> However, with 2/3 of the options presented in the coercive RFC, you'll
>> have an INI setting that changes the behavior of your code for you
>> (the other 1/3 is potentially a significant BC break). How is that
>> better than a per-file switch? Something you as a library developer
>> have no control over...
>
> Personally, I'd prefer no INI switch, but I also recognize the BC
> problems with that RFC. I want to note now, I'm not saying I support
> either RFC specifically; my concern is with the dual-mode aspect of
> the STH v0.5 (and predecessors).
>
> <snip>
>
>>> This is what I want from STH, no more no less: sane casting rules, and the
>>> ability to code to scalar types safely. While I can see some of the 
>>> benefits of
>>> strict mode, I'm concerned about the schism it may create in the PHP library
>>> ecosystem, and that many of the benefits of the coercive portion of that RFC
>>> will be lost when working with data from unknown data sources.
>>
>> Considering the strict mode is file-local, it's not all or nothing.
>> It's up to the author writing code to determine how to handle the
>> calls (s)he will make.
>
> And, as noted, that's the part I need clarification on: is it really
> local only to calls made directly in that file, or does strict follow
> all the way down the chain?

No, it's local only to the call. The mode is specifically file-specific.

> Finally, there's the other aspect of type casting coercion from the
> competing RFC, https://wiki.php.net/rfc/coercive_sth. The tables in
> there make a lot of sense to me, as do the eventual ramifications on
> language consistency. If dual-mode is really restricted only to the
> direct calls made in the given file, and does not travel all the way
> down the callstack, the ideal STH proposal, to me, would be combining
> the aspects of the second proposal with regards to type coercion with
> the dual-mode.

If you mean making the "weak" mode more strict in the dual-mode, then
absolutely. We can and should do it.  But we need to do it in a way
that maintains as much BC as possible (small, sane changes over time).
For example: erroring on "32 apples". That's sane, but is still a BC
break. Hence we need to tread slowly through the options and not just
push a change like that to the basic ZPP behavior through.

Anthony

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

Reply via email to