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