Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:118905 Return-Path: Delivered-To: mailing list internals@lists.php.net Received: (qmail 31789 invoked from network); 28 Oct 2022 17:44:07 -0000 Received: from unknown (HELO php-smtp4.php.net) (45.112.84.5) by pb1.pair.com with SMTP; 28 Oct 2022 17:44:07 -0000 Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id C1D4618005C for ; Fri, 28 Oct 2022 10:44:03 -0700 (PDT) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on php-smtp4.php.net X-Spam-Level: X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2,SPF_HELO_NONE,T_SCC_BODY_TEXT_LINE,T_SPF_TEMPERROR autolearn=no autolearn_force=no version=3.4.2 X-Spam-ASN: AS15169 209.85.128.0/17 X-Spam-Virus: No X-Envelope-From: Received: from mail-lj1-f169.google.com (mail-lj1-f169.google.com [209.85.208.169]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange ECDHE (P-256) server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by php-smtp4.php.net (Postfix) with ESMTPS for ; Fri, 28 Oct 2022 10:44:03 -0700 (PDT) Received: by mail-lj1-f169.google.com with SMTP id b18so9210706ljr.13 for ; Fri, 28 Oct 2022 10:44:03 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=datadoghq.com; s=google; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:from:to:cc:subject:date:message-id:reply-to; bh=CsLLeERrEMxNcxDiuSPL0Qhxv0AVlWr+rwc7p4zBs1E=; b=Fy8zF/YW5NDln77XI6K1WWNKpn5jxnebKfqTgfihtdVs+Dgj5h+CQepLz8910DRXzm O+5cjfkbrRYWF3npgfE8naiba2o+SH+bpZ8bZJ54NpcnZvco2QesmPay5DGMjFT9zRxo wnBK5jPF/I1f9YANz8YAissw4ll5jCF+u7bTk= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=CsLLeERrEMxNcxDiuSPL0Qhxv0AVlWr+rwc7p4zBs1E=; b=8Ax2odZrgigM7ZTWJQNVMx31qlE2woeOmU0ZWSEltLjGhAems0pvb0nAXAz4/en6ZW uU0dv9w8EcNKjsLtu7U+fuQhd8m6r5UjnJCAO2Lh2ZM8udVIS67qkJ8XpJZeTZJhq0dp 9YHJhu8OwGLqlIZE57U+Lauac8WdDSVnsvGJ1Sa8V+ZSueQf2JFXkUXdqCeCbCt/LsNV ED3MvwxqiccS64jQ/rdoOCetvZrDKYRyXAzjnANJo3aSFo7X9oZDFUVw/si2l92Kb7fQ qyTS1QptgML5D9nhXktOL4LNdBt0xf+m2Br1jAUEBHyISoCQfQZZbzzR/656xXKfJVnR SYKQ== X-Gm-Message-State: ACrzQf3Vf1xycEgcW1tDIIIqYnlEDsOlCVAXsJ4bfb2taqqSLi6ySznt elm0mh2Px3Sh+9VaH6Mw/audCp1da8qIZdBcrP6tWm9BJxOmvQ== X-Google-Smtp-Source: AMsMyM71Y78tHWU3isbDQGKQs4XioqK/9HiWTOt15Jhtxf+Rr2wrGWHTqjOd3wB9Q2wFB15BOr6i78rZdeHto0SFh4o= X-Received: by 2002:a2e:9d02:0:b0:277:b0c:44b8 with SMTP id t2-20020a2e9d02000000b002770b0c44b8mr267626lji.528.1666979041618; Fri, 28 Oct 2022 10:44:01 -0700 (PDT) MIME-Version: 1.0 References: In-Reply-To: Reply-To: Levi Morrison Date: Fri, 28 Oct 2022 11:43:50 -0600 Message-ID: To: tyson andre Cc: "internals@lists.php.net" Content-Type: text/plain; charset="UTF-8" Subject: Re: [PHP-DEV] Proposal: Expanded iterable helper functions and aliasing iterator_to_array in `iterable\` namespace From: internals@lists.php.net ("Levi Morrison via internals") > 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.