On Mon, Feb 8, 2021, at 6:48 PM, Levi Morrison via internals wrote:
> On Mon, Feb 8, 2021 at 5:15 PM tyson andre <tysonandre...@hotmail.com> wrote:
> >
> > Hi Larry Garfield,
> >
> > > > Hi Larry Garfield,
> > > >
> > > > > > Hi internals,
> > > > > >
> > > > > > Voting has started on https://wiki.php.net/rfc/any_all_on_iterable 
> > > > > > and
> > > > > > ends on 2021-02-22.
> > > > > >
> > > > > > This RFC proposes to add the functions `PHP\iterable\any(iterable
> > > > > > $input, ?callable $callback = null): bool` and 
> > > > > > `PHP\iterable\all(...)`
> > > > > > to PHP's standard library's function set, using the namespace 
> > > > > > preferred
> > > > > > in the previous straw poll.
> > > > > >
> > > > > > There is a primary vote on whether to add the functions, and a
> > > > > > secondary vote on the name to use within the `PHP\iterable` 
> > > > > > namespace.
> > > > > >
> > > > > > Thanks,
> > > > > > - Tyson
> > > > > > --
> > > > > > PHP Internals - PHP Runtime Development Mailing List
> > > > > > To unsubscribe, visit: https://www.php.net/unsub.php
> > > > >
> > > > >
> > > > > Ak!  I literally just finished reading it and wanted to note a lack 
> > > > > of clarity on one point. :-)
> > > > >
> > > > > The signature of the callback is never specified explicitly.  The 
> > > > > ternary is a bit confusing.  I assume the signature is
> > > > >
> > > > > callable(mixed): bool
> > > > >
> > > > > But that's not made explicit.  It's also not made explict that 
> > > > > omitting the callable collapses to "is truthy".  That's a sensible 
> > > > > thing to do, but it's not stated explicitly anywhere, just inferred 
> > > > > from the code sample.
> > > > >
> > > > > I'm not sure if it's safe to clarify at this point as the vote just 
> > > > > started.
> > > >
> > > > If there is a callable, it allows `callable(mixed): mixed`,
> > > > and converts the callable's return value to a boolean.
> > > > So omitting the callable is the same as passing in the callable `fn($x)
> > > > => $x`, which is equivalent to `fn($x) => (bool)$x`.
> > > > This is exactly what the reference implementation would do.
> > > >
> > > > I definitely should have clarified it instead of assuming that the
> > > > reference implementation was clear enough.
> > > >
> > > > I clarified this and gave examples because the RFC started a few hours
> > > > ago and the implementation didn't change.
> > >
> > > Oof.  I'm glad I asked, because I don't like that at all.  If available, 
> > > the callable should be returning bool, not "anything that may be 
> > > truthy/falsy."  If you have an explicit function, it should have an 
> > > explicit return type.  A truthy check is a reasonable default, but not 
> > > for when you're opting in to specifying the logic.
> > >
> > > I am in favor of the RFC, but I will have to consider if that changes my 
> > > vote to No.
> > >
> > > --Larry Garfield
> >
> > This was a deliberate choice and is consistent with the weak type 
> > comparison behavior of array_filter() and other functions that default to 
> > using weak type checks internally.
> >
> > I'd agree that I'd prefer to see callbacks returning booleans in code I'm 
> > reviewing,
> > but a truthiness check seems more practical and consistent with the rest of 
> > the language
> > than throwing a TypeError or checking the predicate return value using `!== 
> > true`
> >
> > This was made to make PHP more widely accessible and free of surprises.
> > e.g. `(bool)array_filter($arr, $predicate)` can be safely converted to 
> > `any($arr, $predicate)` without introducing a TypeError or behavior change.
> >
> > ```
> > php > var_dump(array_filter([-1,0,1], fn($x)=>$x));
> > array(2) {
> >   [0]=>
> >   int(-1)
> >   [2]=>
> >   int(1)
> > }
> > ```
> >
> > This is the same choice as many other dynamic languages that aren't 
> > compiled ahead of time have made.
> >
> > ```
> > # python
> > >>> any([1])
> > True
> > >>> any([0])
> > False
> > # Ruby
> > irb(main):001:0> [nil].any?
> > => false
> > irb(main):002:0> [false].any?
> > => false
> > irb(main):003:0> !!0
> > => true
> > irb(main):004:0> [0].any?
> > => true
> > # JavaScript
> > > [0].some(x=>x)
> > false
> > > [1].some(x=>x)
> > true
> > ```
> >
> > It is currently possible to check if code is passing a callable returning 
> > anything other than a boolean
> > to functions such as `array_filter()` using a wide variety of static 
> > analyzers/tools, e.g. http://github.com/phan/phan
> >
> > ```
> > <?php
> > // Phan emits "PhanTypeMismatchArgumentInternal Argument 2 ($callback) is 
> > (fn) of type Closure(int):int
> > // but \array_filter() takes 
> > callable(mixed):bool|callable(mixed,mixed):bool"
> > array_filter([1], fn (int $x): int => $x % 3);
> > ```
> >
> > Thanks,
> > -Tyson
> >
> > --
> > PHP Internals - PHP Runtime Development Mailing List
> > To unsubscribe, visit: https://www.php.net/unsub.php
> >
> 
> For what it is worth, in C++ it is fairly normal to use a convertible
> to bool type. For instance, having an overload on a < b for iterators
> can return whatever type it wants, as long as it is contextually
> convertible to bool.

Yet in 8.0, a non-[ 1 | 0 | -1 ] return from a comparison function as just 
converted to a warning.  So the trend in the language seems to be the other 
direction.

--Larry Garfield

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

Reply via email to