Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:115197 Return-Path: Delivered-To: mailing list internals@lists.php.net Received: (qmail 42904 invoked from network); 28 Jun 2021 22:11:03 -0000 Received: from unknown (HELO php-smtp4.php.net) (45.112.84.5) by pb1.pair.com with SMTP; 28 Jun 2021 22:11:03 -0000 Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id 6C9EC1804B3 for ; Mon, 28 Jun 2021 15:30:54 -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,FREEMAIL_FROM, RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H2,SPF_HELO_NONE,SPF_PASS autolearn=no autolearn_force=no version=3.4.2 X-Spam-Virus: No X-Envelope-From: Received: from mail-lf1-f51.google.com (mail-lf1-f51.google.com [209.85.167.51]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange ECDHE (P-256) server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by php-smtp4.php.net (Postfix) with ESMTPS for ; Mon, 28 Jun 2021 15:30:53 -0700 (PDT) Received: by mail-lf1-f51.google.com with SMTP id bp27so10438895lfb.9 for ; Mon, 28 Jun 2021 15:30:53 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=mime-version:in-reply-to:references:from:date:message-id:subject:to :cc:content-transfer-encoding; bh=+GetsfnTpnJbIrUhxrq0GZ9cam9hwha+QY9XYdVWco8=; b=nTpnZy+nFwNSVei09tR9JVQjO5+EjAActaa3IWPblc4u9ZiAE5mG+jF07c/WZ1Ch4w rP2E3xmUzZcDHzOxXgeW+xr8bf5jSXQyHcwyBMjGdL5rfHj2qW9IZlmmpz3IdgB4sCLU ZPmuh4V3oUsUphT1vmx+nFVUCIvttqvJFiqjpjiDP24oBuczIWXzeXK9MDK2lXMrbuI/ +XZxqxUZZFHIyaywl/+sZeLC5juKWP2hqtIKX6EFiBhHRYh6sskOE4Vn+oQfu+Nb+jBI gde/BcWI3h/bTcPMSL9Xovjq1c6+zXyDVUbBSvXGZ1QJAKvgfwYjp/bXvpNIfy7cU+tf ZflA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:in-reply-to:references:from:date :message-id:subject:to:cc:content-transfer-encoding; bh=+GetsfnTpnJbIrUhxrq0GZ9cam9hwha+QY9XYdVWco8=; b=HdiOMkGbmiyxdqvu5AeKgMJC9ndc6BPV1I6sy/Ic+vCZjj6Bt9mjzzuOtigRfi65NC jToGowZ1KX2tPpayqG8v5aZ8jHQnscfW2Wa/mSK5wvT1VbtFtkTMEP2wj6bkvFzDaaEO sAgS+sb1J3Pf0xYr3b/do4fRwlkTSvlntgKk/P9bubOioOeNo8xYEQfbnMDc5rVoiAJA aBTFrxMlMSY4wHhFho7eriET8EEYkpLMbKlNh5wlTQkreB08WBVfD6QOasAPp6WoEBwN 6OisgRCIW1A978QPdBZ+wy0qARNzULpGp3/bSmFejXeMG0wJa4CjttptDWscoGp0c4YI livg== X-Gm-Message-State: AOAM5303QB4MwFICh3qy0GXRoRP8mB2TeWT4Ygem7znJljN1+pq1O6/0 iCD8buVRqOhGsz3q2oQ+XSFeFasKt+/48mmRKKS8CO3O X-Google-Smtp-Source: ABdhPJxe6fp9DTZq0rIBfrKgnnKI2SiNY+c2+stZnwEegMw6q+xOaNNv5a42TxJgg2GS2SDB/8FT6g3CTVkwQULhjdw= X-Received: by 2002:ac2:42d6:: with SMTP id n22mr20188340lfl.41.1624919451271; Mon, 28 Jun 2021 15:30:51 -0700 (PDT) MIME-Version: 1.0 Received: by 2002:ab3:7506:0:0:0:0:0 with HTTP; Mon, 28 Jun 2021 15:30:50 -0700 (PDT) In-Reply-To: References: <43d612c0-7462-463a-9536-ed5b66d9ae1e@www.fastmail.com> Date: Tue, 29 Jun 2021 00:30:50 +0200 Message-ID: To: Larry Garfield Cc: php internals Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable Subject: Re: [PHP-DEV] [RFC] Pipe Operator, take 2 From: olleharstedt@gmail.com (=?UTF-8?Q?Olle_H=C3=A4rstedt?=) 2021-06-28 23:36 GMT+02:00, Larry Garfield : > On Mon, Jun 28, 2021, at 3:42 PM, Olle H=C3=A4rstedt wrote: >> 2021-06-28 22:12 GMT+02:00, Larry Garfield : >> > On Mon, Jun 28, 2021, at 3:04 PM, Rowan Tommins wrote: >> >> On 28/06/2021 20:25, Olle H=C3=A4rstedt wrote: >> >> > Usage (ignoring the pesky undefined constant warnings ><): >> >> >> >> >> >> Unfortunately, you can't ignore those warnings; not least because >> >> they're fatal errors in PHP 8, as they frankly should have been in PH= P >> >> 3. >> >> >> >> You can use our current ugly callable syntax (strings and two-element >> >> arrays); you can tackle the complexity of unifying functions with >> >> constants, and methods with properties (as Levi explained in the othe= r >> >> thread); or you can add a dedicated callable syntax, which the PFA >> >> proposal gets us with bells on. >> >> >> >> Regards, >> > >> > I think that's a pretty good summary. There's nothing that pipes or >> > partials do that you couldn't emulate in user-space today (really, sin= ce >> > 5.3 >> > is you really wanted to). The emulation is just butt-ugly and slower, >> > which >> > is why most people don't do it except in very specific cases or if the= y >> > have >> > a user-space library available that makes it slightly less butt-ugly. >> > >> > The purpose of PFA and pipes (and short functions, and auto-capture >> > closures, and basically everything else I've been talking about all >> > year) is >> > to make those things prettier and as fast as reasonable, which makes >> > using >> > those techniques more natural. Once you start down that path, though, >> > there's really no usable solution before you get down as far as... PFA >> > and >> > Pipes in their current form. >> > >> > --Larry Garfield >> >> The challenge is to write something that's pretty enough to be >> considered idiomatic. :) The pipe operator in OCaml is defined by one >> line: >> >> let (|>) v f =3D f v >> >> It wasn't always part of core, but eventually it was so common, it got >> included by default. Same could happen with a pipe() function in PHP, >> without the pipe operator, or that the function becomes so common, a >> new keyword is added instead: `pipe`. But it could probably not happen >> with a Pipe object requiring you to write ->pipe() at every step - >> it's too much ceremony and boilerplate. >> >> By the way, that's alternative 5) New keyword `pipe` to make the >> warning about constants shut up in a certain scope. Plus some other >> magic to allow nice chaining. ^^ >> >> Olle > > "Idiomatic PHP" consists primarily of associative arrays, used in ways no > sane person would ever use a dictionary, but the code is in a method so i= t > gets called OOP even though it's barely procedural. > > That's not an idiom I have any interest in supporting, and have in fact m= ade > a career out of training people out of. :-) > > There are *already* libraries that let you write ->pipe(). The PHP Leagu= e > has one, for instance: > > https://github.com/thephpleague/pipeline > > I've seen others, but they're no less ugly and offer no better migration > path into a core syntax. PHP is just not designed as a user-extensible > language. (cf, "Growing a Language" by Guy Steele, one of the best > presentations ever given: https://www.youtube.com/watch?v=3D_ahvzDzKdB0) > > Also of note, the OCaml definition there is almost exactly the same as th= e > current patch; there's a request out I'm working on now to change the > implementation to ensure that the LHS is fully evaluated before the RHS, = but > it's interesting to see that OCaml's version does have the out-of-order > challenge. (Although in a functional language it's semantically a > meaningless difference, by design.) > > Overall, I really don't like the idea of special-casing pipes to change w= hat > symbol table gets looked up. That's just asking for edge cases to bite u= s > later, especially when the root problem isn't with pipes in the first pla= ce; > it's with PHP lacking either a function-reference syntax or PFA (which gi= ves > us a function-reference syntax for free). Fix the real problem, don't ha= ck > around it in what should be a very simple feature. > > --Larry Garfield Mm. Assoc arrays are by now known to be not so good. I hope... OCaml is strictly evaluated, not lazy like Haskell. So the order might matter, dunno, I don't use this operator often. :) My point was mostly that it's very easy to add in OCaml - just one line. And as in Haskell, you can define operators in your modules. Similarly, in PHP it's easy to do super-dynamic stuff like "new $someclass", which is not remotely possible in FP (good or bad, depending on your religion). Adding a new pipe keyword is like the list() keyword, kind of. A bad idea, haha. But I think all stones can be turned, if this RFC now gets a no. :/ Would a slimmed down version have more support? How about removing the variadic operator, and let the user manually add the lambda for those cases? Could reduce the complexity while still covering maybe 80% of the use-cases? Same with removing support for named arguments. So '?' would only be a short-cut to get rid of boilerplate like `$strlen =3D fn($x) =3D> strlen($x)`. > Overall, I really don't like the idea of special-casing pipes to change w= hat > symbol table gets looked up. Still wondering if this could be a per-file or per-library setting somehow, to opt-in into pipe behaviour when so desired. Or rather, to opt-in into this or that behaviour needed to do more idiomatic pipe. Here's one boilerplaty pipe: // Original snippet with nested calls and hard-to-follow program flow $result =3D array_filter( array_map( 'strtoupper', str_split( htmlentities("Hello World") ) ), fn($v) =3D> $v !=3D=3D 'O' ); // Boilerplate setup $htmlentities =3D fn($x) =3D> htmlentities($x); $str_split =3D fn($x) =3D> str_split($x); $strtoupper =3D fn($x) =3D> strtoupper($x); // Actual calculation $result =3D pipe( "Hello world", $htmlentities, $str_split, fn ($x) =3D> array_map($strtoupper, $x), fn ($x) =3D> array_filter($x, fn ($v) =3D> $v !=3D=3D 'O') ); Where pipe() is just: function pipe() { $args =3D func_get_args(); $result =3D $args[0]; $functions =3D array_slice($args, 1); foreach ($functions as $function) { $result =3D $function($result); } return $result; } Olle