2021-06-28 23:36 GMT+02:00, Larry Garfield <la...@garfieldtech.com>: > On Mon, Jun 28, 2021, at 3:42 PM, Olle Härstedt wrote: >> 2021-06-28 22:12 GMT+02:00, Larry Garfield <la...@garfieldtech.com>: >> > On Mon, Jun 28, 2021, at 3:04 PM, Rowan Tommins wrote: >> >> On 28/06/2021 20:25, Olle Härstedt 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 PHP >> >> 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 other >> >> 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, since >> > 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 they >> > 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 = 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 it > gets called OOP even though it's barely procedural. > > That's not an idiom I have any interest in supporting, and have in fact made > a career out of training people out of. :-) > > There are *already* libraries that let you write ->pipe(). The PHP League > 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=_ahvzDzKdB0) > > Also of note, the OCaml definition there is almost exactly the same as the > 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 what > symbol table gets looked up. That's just asking for edge cases to bite us > later, especially when the root problem isn't with pipes in the first place; > it's with PHP lacking either a function-reference syntax or PFA (which gives > us a function-reference syntax for free). Fix the real problem, don't hack > 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 = fn($x) => strlen($x)`. > Overall, I really don't like the idea of special-casing pipes to change what > 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 = array_filter( array_map( 'strtoupper', str_split( htmlentities("Hello World") ) ), fn($v) => $v !== 'O' ); // Boilerplate setup $htmlentities = fn($x) => htmlentities($x); $str_split = fn($x) => str_split($x); $strtoupper = fn($x) => strtoupper($x); // Actual calculation $result = pipe( "Hello world", $htmlentities, $str_split, fn ($x) => array_map($strtoupper, $x), fn ($x) => array_filter($x, fn ($v) => $v !== 'O') ); Where pipe() is just: function pipe() { $args = func_get_args(); $result = $args[0]; $functions = array_slice($args, 1); foreach ($functions as $function) { $result = $function($result); } return $result; } Olle -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: https://www.php.net/unsub.php