> Namespaces were chosen after feedback on my previous RFC,
> and I believe `iterable\` follows the guidance from 
> https://wiki.php.net/rfc/namespaces_in_bundled_extensions and
> https://wiki.php.net/rfc/namespaces_in_bundled_extensions#core_standard_spl

I support this general direction :thumbsup:

> I plan to create an RFC with the following functionality in the iterable\ 
> namespace, and wanted to see what the preference on naming was, or if there 
> was other feedback.
> (Not having enough functionality and wanting a better idea of the overall
>
> - `iterable\count(...)` (alias of iterator_count)
> - `iterable\to_array(Traversable $iterator, bool $preserve_keys = true): 
> array` (alias of iterator_to_array, so that users can stop using a misleading 
> name)

At the very least, I'd like to also see `to_array_list` which ensures
that the `array_is_list` invariant is upheld by only using values from
the iterable.

Variants for assoc arrays have to deal with the fact that iterables
have duplicate keys, and also may contain key types which don't work
as array keys.

 1. I think later values overwriting previous values of the same is
generally agreeable.
 2. However, what to do with things that aren't key types I can see
having a lot of discussion. Some people probably just want them to
silently filter out, some people want a warning but to proceed with
the list, others may want a TypeError. I suppose we can make 3
functions, one for each case?
    - `to_assoc_array_silent` which drops things which don't work as array keys.
    - `to_assoc_array_warn` which drops things which don't work as
array keys but also emits a warning.
    - `to_assoc_array_throw` which throws a TypeError if a key doesn't
work as an array key.

Not sure on these assoc things, but I'm pretty sure `to_array_list`
should be included in the very first version.

> - `iterable\any(iterable $input, ?callable $callback = null): bool` - 
> Determines whether any value of the iterable satisfies the predicate.
>    and all() - Determines whether all values of the iterable satisfies the 
> predicate.

:thumbsup:

> - `iterable\none(iterable $input, ?callable $callback = null): bool`
>
>    returns the opposite of any()

:thumbsup:

> - `iterable\find(iterable $iterable, callable $callback, mixed $default = 
> null): mixed`

I would prefer to drop the default and have an Option return type
instead, but we don't have one today.

> - `iterable\fold(iterable $iterable, callable $callback, mixed $initial): 
> mixed`
>
>   `fold` and requiring an initial value seems like better practice. See 
> https://externals.io/message/112558#112834
>   and 
> https://stackoverflow.com/questions/25149359/difference-between-reduce-and-fold

:thumbsup:

If we figure out an optional/result type then I think
`iterable\reduce` which just uses the first item as the initial would
be very helpful, but we have to deal with the empty iterable case so
I'm happy to leave it out for now since we don't have Option.

> - `iterable\unique_values(iterable $iterable): array {}`
>
>   Returns true if this iterable includes a value identical to $value (`===`).

I suppose this should take an optional callback that users can provide
for a custom definition of uniqueness?

> - `iterable\includes_value(iterable $iterable, mixed $value): bool {}`
>    Returns a list of unique values of $iterable

Not sure on this one, but the description doesn't match the signature :)
Anything which does comparison/uniqueness check should have a callback
(or optional callback) for specifying how to do that.

> There's other functionality that I was less certain about proposing, such as 
> `iterable\keys(iterable $iterable): array`,
> which would work similarly to array_keys but also work on Traversables (e.g. 
> to be used with userland/internal collections, generators, etc.)

I assume this doesn't care about key uniqueness -- it takes the keys
and makes them values, in the same order they were returned?

In any case, I don't think this should return an iterable, not array,
to allow for lazy operations in a chain, while also allowing for using
an array as an optimization.

> Or functions to get the iterable\first()/last() value in an iterable. Any 
> thoughts on those?

What do they return on empty? I would prefer to delay these and try to
get an Option type. Otherwise, they require doing a lot of variants
like the following to be ergonomic:
  - first_or($iterable, mixed $default)
  - first_or_else($iterable, callable $callback)
  - last_or($iterable, mixed $default)
  - last_or_else($iterable, callable $callback)

But if we can return an option:

  - first($iterable): Option
  - last($iterable): Option

Then the other parts move to the Option API:
  - `iterable\first($iterable)->unwrap_or($default)`
  - `iterable\first($iterable)->unwrap_or_else(fn () => $whatever)`

This general feedback also applies to `iterable\find()`.

> I also wanted to know if more verbose names such as find_value(), 
> fold_values(), any_values(), all_values() were generally preferred before 
> proposing this,
> since I only had feedback from a small number of names. My assumption was 
> short names were generally preferred when possible.

I like the verbose names when there are variants, for instance `fold`
and `fold_with_keys` (where we provide both key and value). I
definitely do not like it when we change function signatures of
callbacks based on `flags` parameters like some PHP functions do
today.

Phew, I'm not sure the mailing list is the best way to the tidbits of
the APIs! In any case, I strongly support the direction.

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

Reply via email to