Re: [PHP-DEV] pipes, scalar objects and on?

2023-07-20 Thread Jordan LeDoux
On Tue, Jul 18, 2023 at 8:05 AM Robert Landers 
wrote:

> On Tue, Jul 18, 2023 at 3:18 PM Olle Härstedt 
> wrote:
> >
> > 2023-07-18 14:48 GMT+02:00, someniatko :
> > > I am glad this topic arose! I was also planning to write on this topic
> to
> > > the internals mailing list, but have abandoned this idea, because I
> feel it
> > > might be inconvenient for the real active PHP developers on the list to
> > > receive too many emails from the people which don't actively
> participate in
> > > the development itself.
> > >
> > > My interest in the pipe operator might seem a little non-standard -
> > > basically what I'd really want to see is a **nullable** pipe operator!
> > >
> > > There is a popular library github.com/schmittjoh/php-option, which
> has 250
> > > MILLION installations. Basically what it provides is a class-wrapper
> of a
> > > value of lack thereof: it's either `Some` or `None`. I also
> maintain
> > > a similar library
> https://packagist.org/packages/someniatko/result-type
> > > which fixes some shortcomings of the original one related to the static
> > > analysis, but this is another story. Basically what the stats tell us
> is
> > > that such stuff is popular among the PHP community.
> > >
> > > In my eyes, it is actually semantically equivalent to the nullable PHP
> > > types: `?Type`. And some operations provided by the lib, are actually
> > > covered by PHP itself, which has multiple null-friendly operators:
> > > `$option->getOrElse($defaultVal)` --> `$nullable ?? $defaultVal`
> > > `$option->isEmpty()` --> `$nullable === null`
> > > `$option->getOrThrow(new \Exception('blah'))` --> `$nullable ?? throw
> new
> > > \Exception('blah')`
> > >
> > > I'd like to use the arguably "more idiomatic" native PHP nullables,
> rather
> > > than a foreign-feeling userspace construct, if they were more
> convenient.
> > >
> > > But there is a very important operation, `map()`, which is
> unfortunately
> > > not covered by the native PHP, which is `Option::map()`, and here is a
> > > real-world example:
> > > ```
> > > return $repository->getById($idFromHttpRequest)
> > > ->map($serializer->serializeToJson(...)) // only executes when the
> > > Option is Some, not None
> > > ->map(fn (string $json) => new Response(status: 200, content:
> $json))
> > > ->getOrElse(new Response(status: 404));
> > > ```
> >
> > Ehm, wouldn't that be the same as a Pipe class that's configured to
> > stop on null?
> >
> > public function getThing($id) {
> >   return new Pipe(
> > $this->getData(...),
> > $this->serializeData(...),
> > $this->mapToResponse(...)
> >   )
> >   ->stopOnEmpty()
> >   ->from($id)
> >   ->run();
> > }
> >
> > Wait, are you using map() for arrays or not? Looks like not.
> >
> > Olle
> >
> > --
> > PHP Internals - PHP Runtime Development Mailing List
> > To unsubscribe, visit: https://www.php.net/unsub.php
> >
>
> I might be venting, but, I wish the operators RFC had passed...
>

I don't think I will re-propose it with the current set of voters tbh. The
main people who contribute to the Zend folder (the core engine/compiler
parts) were highly skeptical of it, with at least two telling me flat out
that they would vote no even on a hypothetical perfect feature design. Very
few contributors actually touch large parts of that area of the engine, so
most voters tend to take the opinions of those 5-6 voters very seriously on
such proposals. As I don't think it's possible for me to convince those 5-6
people, I don't think it would be a good idea to re-propose, because even
if I did get a 2/3 vote on it, I feel like the people most responsible for
helping me maintain the feature would not be very happy/willing to do so,
and that would probably harm the PHP project in other ways.

Jordan


Re: [PHP-DEV] pipes, scalar objects and on?

2023-07-19 Thread Larry Garfield
On Wed, Jul 19, 2023, at 12:08 PM, Olle Härstedt wrote:
> 2023-07-18 18:50 GMT+02:00, Larry Garfield :
>> On Tue, Jul 18, 2023, at 4:47 PM, Olle Härstedt wrote:
>>
>>> Any comment on a pipe (or piped process) as a first-class value? When
>>> you use |> the functions are immediately applied, which might not be
>>> what you want. You can lazify it by wrapping it in a lambda, but I
>>> think that decreases the value of the pipe concept in itself. One
>>> strength is the ability to split the decision about what to glue
>>> together from the decision on how to execute it. You kinda get some
>>> light-weight metaprogramming ability that way.
>>>
>>> Well i guess such a pipe-concept is pretty far removed from the simple
>>> pipe operator. :) And also already possible with existing OOP
>>> concepts, callable classes, and now the (...) syntax.
>>
>> That's the function concat operator I have been mentioning.  Concat can be
>> implemented in terms of pipe, and pipe can be implemented in terms of
>> concat, but I'd rather have both natively.
>>
>> For more on my thoughts there, see:
>> https://peakd.com/hive-168588/@crell/aoc2021-review
>
> Right, I think I was thinking more of the pipeline design pattern than
> the pipe operator. The concat operator will tell you THAT two
> functions have been glued together, but you have no way to affect HOW
> they are glued together. With the pipeline design pattern, you do: For
> example, you could add a logger that logs each input and output in the
> Pipe class without much hassle.
>
> The pipeline design pattern could still greatly benefit from some of
> these RFCs tho, especially partial function application, I think.
>
> Olle

OK, terminology mismatch.  What you're calling "pipeline design pattern" I'm 
calling "that's literally what a monad is." :-)  (More precisely, monads are 
the mathematical rules that a "fancy function concatenation" operation has to 
follow in order to still be composable cleanly.  You could make pipeline-like 
things that don't follow those rules, but they'd be less useful.)

Your logging example is literally the "writer monad," one of the standard monad 
examples.

--Larry Garfield

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



Re: [PHP-DEV] pipes, scalar objects and on?

2023-07-19 Thread Olle Härstedt
2023-07-18 18:50 GMT+02:00, Larry Garfield :
> On Tue, Jul 18, 2023, at 4:47 PM, Olle Härstedt wrote:
>
>> Any comment on a pipe (or piped process) as a first-class value? When
>> you use |> the functions are immediately applied, which might not be
>> what you want. You can lazify it by wrapping it in a lambda, but I
>> think that decreases the value of the pipe concept in itself. One
>> strength is the ability to split the decision about what to glue
>> together from the decision on how to execute it. You kinda get some
>> light-weight metaprogramming ability that way.
>>
>> Well i guess such a pipe-concept is pretty far removed from the simple
>> pipe operator. :) And also already possible with existing OOP
>> concepts, callable classes, and now the (...) syntax.
>
> That's the function concat operator I have been mentioning.  Concat can be
> implemented in terms of pipe, and pipe can be implemented in terms of
> concat, but I'd rather have both natively.
>
> For more on my thoughts there, see:
> https://peakd.com/hive-168588/@crell/aoc2021-review

Right, I think I was thinking more of the pipeline design pattern than
the pipe operator. The concat operator will tell you THAT two
functions have been glued together, but you have no way to affect HOW
they are glued together. With the pipeline design pattern, you do: For
example, you could add a logger that logs each input and output in the
Pipe class without much hassle.

The pipeline design pattern could still greatly benefit from some of
these RFCs tho, especially partial function application, I think.

Olle

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



Re: [PHP-DEV] pipes, scalar objects and on?

2023-07-18 Thread Olle Härstedt
2023-07-18 21:44 GMT+02:00, Deleu :
> https://wiki.php.net/rfc/short-functions
>> https://wiki.php.net/rfc/auto-capture-closure
>> https://wiki.php.net/rfc/partial_function_application
>> https://wiki.php.net/rfc/pipe-operator-v2
>
>
> The only thing I can think of is if we gather a team of ~20 ppl and come up
> with a plan on collectively getting Voting Karma so that we can have these
> awesomeness revisited.

Or, we gather the main concern(s) of the no-voters and try to approach
those? :) Put them in a sheet (Google or Excel) and try to make sense
out of it, if there's a way forward.

Olle

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



Re: [PHP-DEV] pipes, scalar objects and on?

2023-07-18 Thread Deleu
https://wiki.php.net/rfc/short-functions
> https://wiki.php.net/rfc/auto-capture-closure
> https://wiki.php.net/rfc/partial_function_application
> https://wiki.php.net/rfc/pipe-operator-v2


The only thing I can think of is if we gather a team of ~20 ppl and come up
with a plan on collectively getting Voting Karma so that we can have these
awesomeness revisited.


-- 
Marco Deleu


Re: [PHP-DEV] pipes, scalar objects and on?

2023-07-18 Thread Olle Härstedt
2023-07-18 20:08 GMT+02:00, Larry Garfield :
> On Tue, Jul 18, 2023, at 5:08 PM, Karoly Negyesi wrote:
>> My favorite pipeline is Elixir, where "The pipe operator |> passes the
>> result of an expression as the first parameter of another expression"..
>> But
>> it works there because unlike with PHP, it's almost always the first
>> argument you want. If it's not the first argument you needed to do some
>> tricks which was only cleaned up in 2021 so now they do:
>>
>> 5
>> |> then((1..10, &1))
>> |> Enum.reverse()
>>
>> but I digress.
>>
>> My problem here is... we actually need something that passes the RFC
>> vote.
>>
>> What flexibility is missing here?
>
> Please don't top post.
>
> The main flexibility for callables is the ability to build a closure on the
> fly.  For example, using $$ (which Hack does, and I insist on calling
> T_BLING) means that for array and string functions you still need to worry
> about parameter order.  With a callable, you can effectively emulate
> Elixir's behavior if you want.
>
> For example, my FP library has a whole bunch of higher order functions that
> just return pipe-ready functions:
>
> https://github.com/Crell/fp/blob/master/src/array.php
>
> Which, with a pipe operator, would allow for:
>
> $result = $arr
>   |> amap(trim(...))
>   |> afilter(is_int(...))
>   |> reduce(0, $fn)
>   |> trim(...) // At this point it's a string and trim() is already unary,
> so we can just use it.
> ;
>
> Which is pretty nice, IMO.  It "flows" nicely, supports both higher order
> functions and direct calls equally well, and allows for all kinds of further
> expansion that I haven't thought of yet.
>
> The Hack style would require thinking about the fact that array_map() and
> array_filter() take their arguments in reverse order from each other, which
> is just silly.  This way, that problem goes away entirely.
>
> It also allows a pipe to be used as a quasi alternative to scalar methods,
> because (if we set aside visibility for the moment) a method is just a
> function with an implicit $this parameter.  Callables and higher order
> functions make that a lot cleaner.
>
> The caveat is that it does add an extra step to use many of the existing
> array or string stdlib functions.  However, that's work that can be done
> once.  The link above is under 500 lines, heavily documented, and covers
> every array use case I've run into so far.
>
> Related improvements:
>
> * Writing a higher order function right now is rather cumbersome.  There
> were two previous RFCs that would have made that vastly nicer
> (short-functions and auto-capture closures), but neither passed.  They would
> have allowed for:
>
> function amap(callable $c) => fn (iterable $it): array {
> if (is_array($it)) {
> return array_map($c, $it);
> }
> $result = [];
> foreach ($it as $k => $v) {
> $result[$k] = $c($v);
> }
> return $result;
> };
>
> Which I think is pretty nice.
>
> * PFA would give us the best of both worlds, as if you wanted you could do:
>
> $result = $arr
>   |> array_map(trim(...), ?)
>   |> array_filter(?, is_int(...))
>   |> array_reduce(?, $fn, 0)
>   |> trim(...)
> ;

Damn, that PFA RFC would _really_ help with removing noise, instead of
wrapping with fn ($x) => ... everywhere. Shame it didn't pass. :/ 29
vs 20 votes.

Olle

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



Re: [PHP-DEV] pipes, scalar objects and on?

2023-07-18 Thread Larry Garfield
On Tue, Jul 18, 2023, at 5:08 PM, Karoly Negyesi wrote:
> My favorite pipeline is Elixir, where "The pipe operator |> passes the
> result of an expression as the first parameter of another expression".. But
> it works there because unlike with PHP, it's almost always the first
> argument you want. If it's not the first argument you needed to do some
> tricks which was only cleaned up in 2021 so now they do:
>
> 5
> |> then((1..10, &1))
> |> Enum.reverse()
>
> but I digress.
>
> My problem here is... we actually need something that passes the RFC vote.
>
> What flexibility is missing here?

Please don't top post.

The main flexibility for callables is the ability to build a closure on the 
fly.  For example, using $$ (which Hack does, and I insist on calling T_BLING) 
means that for array and string functions you still need to worry about 
parameter order.  With a callable, you can effectively emulate Elixir's 
behavior if you want.

For example, my FP library has a whole bunch of higher order functions that 
just return pipe-ready functions:

https://github.com/Crell/fp/blob/master/src/array.php

Which, with a pipe operator, would allow for:

$result = $arr
  |> amap(trim(...))
  |> afilter(is_int(...))
  |> reduce(0, $fn)
  |> trim(...) // At this point it's a string and trim() is already unary, so 
we can just use it.
;

Which is pretty nice, IMO.  It "flows" nicely, supports both higher order 
functions and direct calls equally well, and allows for all kinds of further 
expansion that I haven't thought of yet.  

The Hack style would require thinking about the fact that array_map() and 
array_filter() take their arguments in reverse order from each other, which is 
just silly.  This way, that problem goes away entirely.

It also allows a pipe to be used as a quasi alternative to scalar methods, 
because (if we set aside visibility for the moment) a method is just a function 
with an implicit $this parameter.  Callables and higher order functions make 
that a lot cleaner.

The caveat is that it does add an extra step to use many of the existing array 
or string stdlib functions.  However, that's work that can be done once.  The 
link above is under 500 lines, heavily documented, and covers every array use 
case I've run into so far.  

Related improvements:

* Writing a higher order function right now is rather cumbersome.  There were 
two previous RFCs that would have made that vastly nicer (short-functions and 
auto-capture closures), but neither passed.  They would have allowed for:

function amap(callable $c) => fn (iterable $it): array {
if (is_array($it)) {
return array_map($c, $it);
}
$result = [];
foreach ($it as $k => $v) {
$result[$k] = $c($v);
}
return $result;
};

Which I think is pretty nice.

* PFA would give us the best of both worlds, as if you wanted you could do:

$result = $arr
  |> array_map(trim(...), ?)
  |> array_filter(?, is_int(...))
  |> array_reduce(?, $fn, 0)
  |> trim(...)
;

So with PFA and callable pipes, we get both options.  If pipe was just 
Hack-style, there would be no way to use higher order functions with it.

So IMO, the ideal experience that gets almost everyone what they want would be 
if all four of the following had passed:

https://wiki.php.net/rfc/short-functions
https://wiki.php.net/rfc/auto-capture-closure
https://wiki.php.net/rfc/partial_function_application
https://wiki.php.net/rfc/pipe-operator-v2

They are all mutually-complementary, but also useful on their own, and were 
designed that way deliberately.  Sadly, all four were declined.

So yeah, it's great that there's renewed interest in pipes, but I've already 
sunk a ton of time into this space (as have many other people that helped with 
those RFCs) with nothing to show for it.  Unless there's indication from a 
notable number of voters that they'd support it now, I'm reluctant to sink much 
more of my time (or anyone else's time) into something that has so far just run 
into brick walls.

If any of the above has convinced someone that we should try any of these 
features again, please speak up.  I seriously do want this functionality, but 
OSS spec work is not my favorite way to spend time.

--Larry Garfield

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



Re: [PHP-DEV] pipes, scalar objects and on?

2023-07-18 Thread Karoly Negyesi
My favorite pipeline is Elixir, where "The pipe operator |> passes the
result of an expression as the first parameter of another expression".. But
it works there because unlike with PHP, it's almost always the first
argument you want. If it's not the first argument you needed to do some
tricks which was only cleaned up in 2021 so now they do:

5
|> then((1..10, &1))
|> Enum.reverse()

but I digress.

My problem here is... we actually need something that passes the RFC vote.

What flexibility is missing here?


On Tue, Jul 18, 2023 at 6:48 PM Larry Garfield 
wrote:

> On Tue, Jul 18, 2023, at 4:41 PM, Karoly Negyesi wrote:
> > So. Let's get back to pipelines.
> >
> > I wrote this email because I was manipulating a robots meta tag string:
> >
> > $robots_array = explode(', ', $robots_string);
> > $robots_array = array_diff($robots_array, $remove);
> > $robots_string = implode(', ', $robots_array);
> >
> > Very pipeline-ish.
> >
> > You could write a userspace pipeline
> > https://gist.github.com/chx/6638aba76d8b414ffedc7e5af78fb479 but this
> has
> > the advantage of being spectacularly ugly and slow as well.
> >
> > Just converting it into a pipeline with
> >
> > $robots_string
> > |>  fn ($x) => explode(', ', $x)
> > |> fn ($x) => array_diff($x, $remove)
> > |> fn ($x) => implode(', ', $x)
> >
> > has the same characteristics. What I would love to see:
> >
> > $robots_string
> > |> explode(', ', $)
> > |> array_diff($, $remove)
> > |> implode(', ', $)
> >
> > While that does look like partial function application, it does not need
> to
> > be. It could be just syntactic sugar. Namely, in the expression following
> > |> a $ is replaced by the entire expression before the |>. Step by step:
> >
> > explode(', ', $robots_string)
> > |> array_diff($, $remove)
> > |> implode(', ', $)
> >
> > array_diff(explode(', ', $robots_string), $remove)
> > |> implode(', ', $)
> >
> > implode(', ', array_diff(explode(', ', $robots_string), $remove))
> >
> > We could use any other symbol but I liked the $ sign here because the
> > entire point is not needing a temporary variable between steps so the $
> > sign stands for "unnamed temporary variable". I also believe it can't
> lead
> > to any ambiguous situation (famous last words).
> >
> > What do you think of this simple version?
>
> That's what Hack does, and what no other language does.  I dislike it as
> it's actually much less flexible overall.  It's also more work to implement.
>
> The original idea was that combining real PFA with a callable-based pipe
> would give us the same net effect if we wanted it, but with greater
> flexibility and more power across the whole language.  Unfortunately the
> PFA RFC barely didn't pass, due to its complexity.  A nicer implementation,
> if it could be found, would probably pass.
>
> --Larry Garfield
>


Re: [PHP-DEV] pipes, scalar objects and on?

2023-07-18 Thread Larry Garfield
On Tue, Jul 18, 2023, at 4:47 PM, Olle Härstedt wrote:

> Any comment on a pipe (or piped process) as a first-class value? When
> you use |> the functions are immediately applied, which might not be
> what you want. You can lazify it by wrapping it in a lambda, but I
> think that decreases the value of the pipe concept in itself. One
> strength is the ability to split the decision about what to glue
> together from the decision on how to execute it. You kinda get some
> light-weight metaprogramming ability that way.
>
> Well i guess such a pipe-concept is pretty far removed from the simple
> pipe operator. :) And also already possible with existing OOP
> concepts, callable classes, and now the (...) syntax.

That's the function concat operator I have been mentioning.  Concat can be 
implemented in terms of pipe, and pipe can be implemented in terms of concat, 
but I'd rather have both natively.

For more on my thoughts there, see: 
https://peakd.com/hive-168588/@crell/aoc2021-review

--Larry Garfield

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



Re: [PHP-DEV] pipes, scalar objects and on?

2023-07-18 Thread Larry Garfield
On Tue, Jul 18, 2023, at 4:41 PM, Karoly Negyesi wrote:
> So. Let's get back to pipelines.
>
> I wrote this email because I was manipulating a robots meta tag string:
>
> $robots_array = explode(', ', $robots_string);
> $robots_array = array_diff($robots_array, $remove);
> $robots_string = implode(', ', $robots_array);
>
> Very pipeline-ish.
>
> You could write a userspace pipeline
> https://gist.github.com/chx/6638aba76d8b414ffedc7e5af78fb479 but this has
> the advantage of being spectacularly ugly and slow as well.
>
> Just converting it into a pipeline with
>
> $robots_string
> |>  fn ($x) => explode(', ', $x)
> |> fn ($x) => array_diff($x, $remove)
> |> fn ($x) => implode(', ', $x)
>
> has the same characteristics. What I would love to see:
>
> $robots_string
> |> explode(', ', $)
> |> array_diff($, $remove)
> |> implode(', ', $)
>
> While that does look like partial function application, it does not need to
> be. It could be just syntactic sugar. Namely, in the expression following
> |> a $ is replaced by the entire expression before the |>. Step by step:
>
> explode(', ', $robots_string)
> |> array_diff($, $remove)
> |> implode(', ', $)
>
> array_diff(explode(', ', $robots_string), $remove)
> |> implode(', ', $)
>
> implode(', ', array_diff(explode(', ', $robots_string), $remove))
>
> We could use any other symbol but I liked the $ sign here because the
> entire point is not needing a temporary variable between steps so the $
> sign stands for "unnamed temporary variable". I also believe it can't lead
> to any ambiguous situation (famous last words).
>
> What do you think of this simple version?

That's what Hack does, and what no other language does.  I dislike it as it's 
actually much less flexible overall.  It's also more work to implement.

The original idea was that combining real PFA with a callable-based pipe would 
give us the same net effect if we wanted it, but with greater flexibility and 
more power across the whole language.  Unfortunately the PFA RFC barely didn't 
pass, due to its complexity.  A nicer implementation, if it could be found, 
would probably pass.

--Larry Garfield

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



Re: [PHP-DEV] pipes, scalar objects and on?

2023-07-18 Thread Olle Härstedt
2023-07-18 17:13 GMT+02:00, Larry Garfield :
> On Tue, Jul 18, 2023, at 1:05 PM, Olle Härstedt wrote:
>> 2023-07-18 14:48 GMT+02:00, someniatko :
>>> I am glad this topic arose! I was also planning to write on this topic
>>> to
>>> the internals mailing list, but have abandoned this idea, because I feel
>>> it
>>> might be inconvenient for the real active PHP developers on the list to
>>> receive too many emails from the people which don't actively participate
>>> in
>>> the development itself.
>>>
>>> My interest in the pipe operator might seem a little non-standard -
>>> basically what I'd really want to see is a **nullable** pipe operator!
>>>
>>> There is a popular library github.com/schmittjoh/php-option, which has
>>> 250
>>> MILLION installations. Basically what it provides is a class-wrapper of
>>> a
>>> value of lack thereof: it's either `Some` or `None`.
>>
>> I'd just like to mention that the Option type comes from FP and it's
>> not necessarily needed in PHP-land where we have flow-sensitive type
>> checkers like Psalm (a nullable type `?int` or such is refined to just
>> `int` after a null check). Flow-sensitive type-checking was not
>> invented when the Option type was first created, so adding it to PHP
>> is basically stepping back in time, from my point of view.
>
> As I've written before[1], there's a lot of overlap in different
> error-flow-control options.  PHP at the moment leans heavily on the "null is
> error and build tooling around that" approach, which has its pros (mainly
> simplicity) and cons (lack of information).  That mostly obviates the need
> for a Maybe type, but not entirely.  Right now, there is no "null pipeline"
> option in the language like someniako is describing.
>
> In some sense, that's also trivial to do in user-space[2], which leads
> easily to
>
> $foo
>   |> maybe(bar(...))
>   |> maybe(baz(...))
>   |> maybe(beep(...));
>
> Which isn't terrible, but also isn't ideal.  I don't think I'd oppose a
> nullsafe pipe if there's interest (though again, we need interest in pipes
> in general first).
>
> However, that runs into the related problem that Maybe is... the weaker way
> of handling error context.  In most cases I prefer a Result/Either type,
> which doesn't map cleanly to null handling.  That could be done as a
> user-space monad (as above, with just a class and method or a magic method
> and dedicated operator).  Doing it more natively would require deeper
> language hooks.  For instance, Rust has the ? suffix on any expression,
> which means "if this evaluates to an Error case Result, just return that
> Result."  That wouldn't fit well in PHP, though.
>
> As I noted in [1], one option would be to allow an object to flag itself as
> an error object, and then null-check operators would treat that as null.  So
> given $result = foo($a)->bar(), if foo() returns an error object then
> $result is assigned to that error object and bar() is never called.  I'm
> still not sure if I like that approach myself, but am open to hear what
> others think.
>
> To get back on topic, I do think a pipe operator and concat operator are
> valuable in their own right, and have ample use cases even without mixing in
> monads or nullables or things like that.  We should add them.  We can
> consider adding more robust branching options as well, (be that >>=, ?|>, or
> something else), but be aware that beyond the very trivial case that will
> necessarily involve user-space code for many use cases and we'll need to
> support that.  (Which basically comes down to >>= and making monadic classes
> easier to work with, but also runs into the generics problem, and that's its
> own mess.)
>
> [1] https://peakd.com/hive-168588/@crell/much-ado-about-null
> [2] https://github.com/Crell/fp/blob/master/src/composition.php#L39
>
> --Larry Garfield
>

Any comment on a pipe (or piped process) as a first-class value? When
you use |> the functions are immediately applied, which might not be
what you want. You can lazify it by wrapping it in a lambda, but I
think that decreases the value of the pipe concept in itself. One
strength is the ability to split the decision about what to glue
together from the decision on how to execute it. You kinda get some
light-weight metaprogramming ability that way.

Well i guess such a pipe-concept is pretty far removed from the simple
pipe operator. :) And also already possible with existing OOP
concepts, callable classes, and now the (...) syntax.

Olle

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



Re: [PHP-DEV] pipes, scalar objects and on?

2023-07-18 Thread Karoly Negyesi
So. Let's get back to pipelines.

I wrote this email because I was manipulating a robots meta tag string:

$robots_array = explode(', ', $robots_string);
$robots_array = array_diff($robots_array, $remove);
$robots_string = implode(', ', $robots_array);

Very pipeline-ish.

You could write a userspace pipeline
https://gist.github.com/chx/6638aba76d8b414ffedc7e5af78fb479 but this has
the advantage of being spectacularly ugly and slow as well.

Just converting it into a pipeline with

$robots_string
|>  fn ($x) => explode(', ', $x)
|> fn ($x) => array_diff($x, $remove)
|> fn ($x) => implode(', ', $x)

has the same characteristics. What I would love to see:

$robots_string
|> explode(', ', $)
|> array_diff($, $remove)
|> implode(', ', $)

While that does look like partial function application, it does not need to
be. It could be just syntactic sugar. Namely, in the expression following
|> a $ is replaced by the entire expression before the |>. Step by step:

explode(', ', $robots_string)
|> array_diff($, $remove)
|> implode(', ', $)

array_diff(explode(', ', $robots_string), $remove)
|> implode(', ', $)

implode(', ', array_diff(explode(', ', $robots_string), $remove))

We could use any other symbol but I liked the $ sign here because the
entire point is not needing a temporary variable between steps so the $
sign stands for "unnamed temporary variable". I also believe it can't lead
to any ambiguous situation (famous last words).

What do you think of this simple version?



On Tue, Jul 18, 2023 at 2:57 PM Olle Härstedt 
wrote:

> 2023-07-17 21:57 GMT+02:00, Larry Garfield :
> > On Mon, Jul 17, 2023, at 7:07 PM, Olle Härstedt wrote:
> >> 2023-07-17 18:58 GMT+02:00, Larry Garfield :
> >>> On Mon, Jul 17, 2023, at 2:57 PM, Olle Härstedt wrote:
>  2023-07-17 14:25 GMT+02:00, Karoly Negyesi :
> > Hi,
> >
> > I tried to read on why the pipe RFC failed but by and large I also
> > failed.
> >
> > The discussion on https://github.com/php/php-src/pull/7214 is very
> > short.
> >
> > https://externals.io/message/114770 is not so short but it seems not
> > to
> > cover the latest version which uses first class functions?
> >
> > Could someone please give me a summary why it failed? I really would
> > like
> > to see it succeed :) I am writing code if not daily but certainly
> > weekly
> > that certainly looks like a pipeline.
> 
>  The pipe RFC was kinda forced in before a deadline, no?
> 
>  My own two cents:
> 
>  * It's trivial to implement a pipe() function or a Pipe class
>  * A Pipe class is better than both a function and built-in operator,
>  since it can be configured with custom behaviour, e.g. stop or throw
>  on empty payload, or repeat on a collection, or even with parallelism
>  or concurrency
>  * If I had voting rights, I'd vote in favor in a pipe operator :)
> >>>
> >>> From my recollection, there were a couple of things involved.
> >>>
> >>> 1. It was intended to pair with the PFA RFC, which didn't pass, which
> >>> made
> >>> it a bit less compelling.
> >>> 2. It was close to the RFC deadline, and it seems people get squeamish
> >>> around that.
> >>> 3. Some folks wanted Hack-style pipes instead of the pipes used by
> every
> >>> other language with pipes. I've written before on why that's a worse
> >>> design.
> >>> 4. Arguments that it can be done in user space, which is not true, as I
> >>> have
> >>> a user-space implementation and it's comparatively cumbersome and
> >>> definitely
> >>> slower than a native operator would be.
> >>> 5. General "meh" attitude on FP features in general from some people.
> >>>
> >>> Side note to Olle: If you want a customizable pipe, you've just
> described
> >>> a
> >>> Monad. :-)  It's literally "contextually-sensitive func concatenation."
> >>> A
> >>> monadic bind operator would be harder to do with PHP's weaker type
> >>> system,
> >>> but there are ways it could be done.
> >>
> >> Mm I don't really agree with that, I think monads make sense only in
> >> languages which support them syntactically. A Pipe class is a very
> >> straight-forward construction, and the blog posts I've read about
> >> monads in PHP don't look pretty at all; lots of syntactic noise going
> >> on. But that's another discussion... :)
> >
> > At its most basic:
> >
> > class Foo {
> >   public function __construct(public readonly mixed $val) {}
> >
> >   public __bind(callable $c) {
> > return $c($this->val);
> >   }
> > }
> >
> > new Foo('beep') >>= func(...);
> >
> > Where >>= is the operator that translates to "Call __bind() on the LHS
> > object with the callable on the RHS."  Poof, we now have a monad
> operator.
> > This one is effectively the same as |> as it doesn't do anything, but you
> > can do whatever you want in the __bind() method.
>
> 1. You also want syntactic sugar around this to "flatten" monadic
> usage; in OCaml it's `let*`.
>
> 2. This way you won't 

Re: [PHP-DEV] pipes, scalar objects and on?

2023-07-18 Thread Craig Francis
On 18 Jul 2023, at 16:13, Larry Garfield  wrote:
> PHP at the moment leans heavily on the "null is error and build tooling 
> around that" approach


Yep, you should never use NULL in your code, the following is catastrophically 
bad...

 
$search = ($_GET['q'] ?? NULL);

$search = (isset($_GET['q']) ? $_GET['q'] : NULL); // Pre PHP 7
 
$search = filter_input(INPUT_GET, 'q');
 
$search = $request->input('q'); // Laravel
$search = $request->get('q'); // Symfony
$search = $this->request->getQuery('q'); // CakePHP
$search = $request->getGet('q'); // CodeIgniter

$search = json_decode('{"q":null}');


And all fields in the database must be set to NOT NULL, never use things like 
LEFT JOIN, etc... :-(


Craig

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



Re: [PHP-DEV] pipes, scalar objects and on?

2023-07-18 Thread Larry Garfield
On Tue, Jul 18, 2023, at 1:05 PM, Olle Härstedt wrote:
> 2023-07-18 14:48 GMT+02:00, someniatko :
>> I am glad this topic arose! I was also planning to write on this topic to
>> the internals mailing list, but have abandoned this idea, because I feel it
>> might be inconvenient for the real active PHP developers on the list to
>> receive too many emails from the people which don't actively participate in
>> the development itself.
>>
>> My interest in the pipe operator might seem a little non-standard -
>> basically what I'd really want to see is a **nullable** pipe operator!
>>
>> There is a popular library github.com/schmittjoh/php-option, which has 250
>> MILLION installations. Basically what it provides is a class-wrapper of a
>> value of lack thereof: it's either `Some` or `None`.
>
> I'd just like to mention that the Option type comes from FP and it's
> not necessarily needed in PHP-land where we have flow-sensitive type
> checkers like Psalm (a nullable type `?int` or such is refined to just
> `int` after a null check). Flow-sensitive type-checking was not
> invented when the Option type was first created, so adding it to PHP
> is basically stepping back in time, from my point of view.

As I've written before[1], there's a lot of overlap in different 
error-flow-control options.  PHP at the moment leans heavily on the "null is 
error and build tooling around that" approach, which has its pros (mainly 
simplicity) and cons (lack of information).  That mostly obviates the need for 
a Maybe type, but not entirely.  Right now, there is no "null pipeline" option 
in the language like someniako is describing.

In some sense, that's also trivial to do in user-space[2], which leads easily to

$foo 
  |> maybe(bar(...)) 
  |> maybe(baz(...))
  |> maybe(beep(...));

Which isn't terrible, but also isn't ideal.  I don't think I'd oppose a 
nullsafe pipe if there's interest (though again, we need interest in pipes in 
general first).

However, that runs into the related problem that Maybe is... the weaker way of 
handling error context.  In most cases I prefer a Result/Either type, which 
doesn't map cleanly to null handling.  That could be done as a user-space monad 
(as above, with just a class and method or a magic method and dedicated 
operator).  Doing it more natively would require deeper language hooks.  For 
instance, Rust has the ? suffix on any expression, which means "if this 
evaluates to an Error case Result, just return that Result."  That wouldn't fit 
well in PHP, though.

As I noted in [1], one option would be to allow an object to flag itself as an 
error object, and then null-check operators would treat that as null.  So given 
$result = foo($a)->bar(), if foo() returns an error object then $result is 
assigned to that error object and bar() is never called.  I'm still not sure if 
I like that approach myself, but am open to hear what others think.

To get back on topic, I do think a pipe operator and concat operator are 
valuable in their own right, and have ample use cases even without mixing in 
monads or nullables or things like that.  We should add them.  We can consider 
adding more robust branching options as well, (be that >>=, ?|>, or something 
else), but be aware that beyond the very trivial case that will necessarily 
involve user-space code for many use cases and we'll need to support that.  
(Which basically comes down to >>= and making monadic classes easier to work 
with, but also runs into the generics problem, and that's its own mess.)

[1] https://peakd.com/hive-168588/@crell/much-ado-about-null
[2] https://github.com/Crell/fp/blob/master/src/composition.php#L39

--Larry Garfield

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



Re: [PHP-DEV] pipes, scalar objects and on?

2023-07-18 Thread Robert Landers
On Tue, Jul 18, 2023 at 3:18 PM Olle Härstedt  wrote:
>
> 2023-07-18 14:48 GMT+02:00, someniatko :
> > I am glad this topic arose! I was also planning to write on this topic to
> > the internals mailing list, but have abandoned this idea, because I feel it
> > might be inconvenient for the real active PHP developers on the list to
> > receive too many emails from the people which don't actively participate in
> > the development itself.
> >
> > My interest in the pipe operator might seem a little non-standard -
> > basically what I'd really want to see is a **nullable** pipe operator!
> >
> > There is a popular library github.com/schmittjoh/php-option, which has 250
> > MILLION installations. Basically what it provides is a class-wrapper of a
> > value of lack thereof: it's either `Some` or `None`. I also maintain
> > a similar library https://packagist.org/packages/someniatko/result-type
> > which fixes some shortcomings of the original one related to the static
> > analysis, but this is another story. Basically what the stats tell us is
> > that such stuff is popular among the PHP community.
> >
> > In my eyes, it is actually semantically equivalent to the nullable PHP
> > types: `?Type`. And some operations provided by the lib, are actually
> > covered by PHP itself, which has multiple null-friendly operators:
> > `$option->getOrElse($defaultVal)` --> `$nullable ?? $defaultVal`
> > `$option->isEmpty()` --> `$nullable === null`
> > `$option->getOrThrow(new \Exception('blah'))` --> `$nullable ?? throw new
> > \Exception('blah')`
> >
> > I'd like to use the arguably "more idiomatic" native PHP nullables, rather
> > than a foreign-feeling userspace construct, if they were more convenient.
> >
> > But there is a very important operation, `map()`, which is unfortunately
> > not covered by the native PHP, which is `Option::map()`, and here is a
> > real-world example:
> > ```
> > return $repository->getById($idFromHttpRequest)
> > ->map($serializer->serializeToJson(...)) // only executes when the
> > Option is Some, not None
> > ->map(fn (string $json) => new Response(status: 200, content: $json))
> > ->getOrElse(new Response(status: 404));
> > ```
>
> Ehm, wouldn't that be the same as a Pipe class that's configured to
> stop on null?
>
> public function getThing($id) {
>   return new Pipe(
> $this->getData(...),
> $this->serializeData(...),
> $this->mapToResponse(...)
>   )
>   ->stopOnEmpty()
>   ->from($id)
>   ->run();
> }
>
> Wait, are you using map() for arrays or not? Looks like not.
>
> Olle
>
> --
> PHP Internals - PHP Runtime Development Mailing List
> To unsubscribe, visit: https://www.php.net/unsub.php
>

I might be venting, but, I wish the operators RFC had passed...

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



Re: [PHP-DEV] pipes, scalar objects and on?

2023-07-18 Thread Olle Härstedt
2023-07-18 14:48 GMT+02:00, someniatko :
> I am glad this topic arose! I was also planning to write on this topic to
> the internals mailing list, but have abandoned this idea, because I feel it
> might be inconvenient for the real active PHP developers on the list to
> receive too many emails from the people which don't actively participate in
> the development itself.
>
> My interest in the pipe operator might seem a little non-standard -
> basically what I'd really want to see is a **nullable** pipe operator!
>
> There is a popular library github.com/schmittjoh/php-option, which has 250
> MILLION installations. Basically what it provides is a class-wrapper of a
> value of lack thereof: it's either `Some` or `None`. I also maintain
> a similar library https://packagist.org/packages/someniatko/result-type
> which fixes some shortcomings of the original one related to the static
> analysis, but this is another story. Basically what the stats tell us is
> that such stuff is popular among the PHP community.
>
> In my eyes, it is actually semantically equivalent to the nullable PHP
> types: `?Type`. And some operations provided by the lib, are actually
> covered by PHP itself, which has multiple null-friendly operators:
> `$option->getOrElse($defaultVal)` --> `$nullable ?? $defaultVal`
> `$option->isEmpty()` --> `$nullable === null`
> `$option->getOrThrow(new \Exception('blah'))` --> `$nullable ?? throw new
> \Exception('blah')`
>
> I'd like to use the arguably "more idiomatic" native PHP nullables, rather
> than a foreign-feeling userspace construct, if they were more convenient.
>
> But there is a very important operation, `map()`, which is unfortunately
> not covered by the native PHP, which is `Option::map()`, and here is a
> real-world example:
> ```
> return $repository->getById($idFromHttpRequest)
> ->map($serializer->serializeToJson(...)) // only executes when the
> Option is Some, not None
> ->map(fn (string $json) => new Response(status: 200, content: $json))
> ->getOrElse(new Response(status: 404));
> ```

Ehm, wouldn't that be the same as a Pipe class that's configured to
stop on null?

public function getThing($id) {
  return new Pipe(
$this->getData(...),
$this->serializeData(...),
$this->mapToResponse(...)
  )
  ->stopOnEmpty()
  ->from($id)
  ->run();
}

Wait, are you using map() for arrays or not? Looks like not.

Olle

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



Re: [PHP-DEV] pipes, scalar objects and on?

2023-07-18 Thread Olle Härstedt
2023-07-18 14:48 GMT+02:00, someniatko :
> I am glad this topic arose! I was also planning to write on this topic to
> the internals mailing list, but have abandoned this idea, because I feel it
> might be inconvenient for the real active PHP developers on the list to
> receive too many emails from the people which don't actively participate in
> the development itself.
>
> My interest in the pipe operator might seem a little non-standard -
> basically what I'd really want to see is a **nullable** pipe operator!
>
> There is a popular library github.com/schmittjoh/php-option, which has 250
> MILLION installations. Basically what it provides is a class-wrapper of a
> value of lack thereof: it's either `Some` or `None`.

I'd just like to mention that the Option type comes from FP and it's
not necessarily needed in PHP-land where we have flow-sensitive type
checkers like Psalm (a nullable type `?int` or such is refined to just
`int` after a null check). Flow-sensitive type-checking was not
invented when the Option type was first created, so adding it to PHP
is basically stepping back in time, from my point of view.

Olle

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



Re: [PHP-DEV] pipes, scalar objects and on?

2023-07-18 Thread Olle Härstedt
2023-07-17 21:57 GMT+02:00, Larry Garfield :
> On Mon, Jul 17, 2023, at 7:07 PM, Olle Härstedt wrote:
>> 2023-07-17 18:58 GMT+02:00, Larry Garfield :
>>> On Mon, Jul 17, 2023, at 2:57 PM, Olle Härstedt wrote:
 2023-07-17 14:25 GMT+02:00, Karoly Negyesi :
> Hi,
>
> I tried to read on why the pipe RFC failed but by and large I also
> failed.
>
> The discussion on https://github.com/php/php-src/pull/7214 is very
> short.
>
> https://externals.io/message/114770 is not so short but it seems not
> to
> cover the latest version which uses first class functions?
>
> Could someone please give me a summary why it failed? I really would
> like
> to see it succeed :) I am writing code if not daily but certainly
> weekly
> that certainly looks like a pipeline.

 The pipe RFC was kinda forced in before a deadline, no?

 My own two cents:

 * It's trivial to implement a pipe() function or a Pipe class
 * A Pipe class is better than both a function and built-in operator,
 since it can be configured with custom behaviour, e.g. stop or throw
 on empty payload, or repeat on a collection, or even with parallelism
 or concurrency
 * If I had voting rights, I'd vote in favor in a pipe operator :)
>>>
>>> From my recollection, there were a couple of things involved.
>>>
>>> 1. It was intended to pair with the PFA RFC, which didn't pass, which
>>> made
>>> it a bit less compelling.
>>> 2. It was close to the RFC deadline, and it seems people get squeamish
>>> around that.
>>> 3. Some folks wanted Hack-style pipes instead of the pipes used by every
>>> other language with pipes. I've written before on why that's a worse
>>> design.
>>> 4. Arguments that it can be done in user space, which is not true, as I
>>> have
>>> a user-space implementation and it's comparatively cumbersome and
>>> definitely
>>> slower than a native operator would be.
>>> 5. General "meh" attitude on FP features in general from some people.
>>>
>>> Side note to Olle: If you want a customizable pipe, you've just described
>>> a
>>> Monad. :-)  It's literally "contextually-sensitive func concatenation."
>>> A
>>> monadic bind operator would be harder to do with PHP's weaker type
>>> system,
>>> but there are ways it could be done.
>>
>> Mm I don't really agree with that, I think monads make sense only in
>> languages which support them syntactically. A Pipe class is a very
>> straight-forward construction, and the blog posts I've read about
>> monads in PHP don't look pretty at all; lots of syntactic noise going
>> on. But that's another discussion... :)
>
> At its most basic:
>
> class Foo {
>   public function __construct(public readonly mixed $val) {}
>
>   public __bind(callable $c) {
> return $c($this->val);
>   }
> }
>
> new Foo('beep') >>= func(...);
>
> Where >>= is the operator that translates to "Call __bind() on the LHS
> object with the callable on the RHS."  Poof, we now have a monad operator.
> This one is effectively the same as |> as it doesn't do anything, but you
> can do whatever you want in the __bind() method.

1. You also want syntactic sugar around this to "flatten" monadic
usage; in OCaml it's `let*`.

2. This way you won't get read-process-write pipelines as first-class
values, which you can do if you just make a Pipe class instead. I
think. Correct me if I'm wrong. :)

Olle

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



Re: [PHP-DEV] pipes, scalar objects and on?

2023-07-18 Thread someniatko
I am glad this topic arose! I was also planning to write on this topic to
the internals mailing list, but have abandoned this idea, because I feel it
might be inconvenient for the real active PHP developers on the list to
receive too many emails from the people which don't actively participate in
the development itself.

My interest in the pipe operator might seem a little non-standard -
basically what I'd really want to see is a **nullable** pipe operator!

There is a popular library github.com/schmittjoh/php-option, which has 250
MILLION installations. Basically what it provides is a class-wrapper of a
value of lack thereof: it's either `Some` or `None`. I also maintain
a similar library https://packagist.org/packages/someniatko/result-type
which fixes some shortcomings of the original one related to the static
analysis, but this is another story. Basically what the stats tell us is
that such stuff is popular among the PHP community.

In my eyes, it is actually semantically equivalent to the nullable PHP
types: `?Type`. And some operations provided by the lib, are actually
covered by PHP itself, which has multiple null-friendly operators:
`$option->getOrElse($defaultVal)` --> `$nullable ?? $defaultVal`
`$option->isEmpty()` --> `$nullable === null`
`$option->getOrThrow(new \Exception('blah'))` --> `$nullable ?? throw new
\Exception('blah')`

I'd like to use the arguably "more idiomatic" native PHP nullables, rather
than a foreign-feeling userspace construct, if they were more convenient.

But there is a very important operation, `map()`, which is unfortunately
not covered by the native PHP, which is `Option::map()`, and here is a
real-world example:
```
return $repository->getById($idFromHttpRequest)
->map($serializer->serializeToJson(...)) // only executes when the
Option is Some, not None
->map(fn (string $json) => new Response(status: 200, content: $json))
->getOrElse(new Response(status: 404));
```

I'd really like to write such code in a native way:
```
return $repository->getById($idFromHttpRequest)
?|> $serializer->serializeToJson($$)
?|> new Response(status: 200, content: $$)
?? new Response(status: 404);
```

Notice I use the old syntax here, using `$$` as a "piped" intermediate
result variable, mostly because I'd like to use arbitrary PHP expressions,
instead of piping functions only. I feel this is more natural for the PHP
than the more functional-oriented way. I am okay with using functions too
like this:

```
return $repository->getById($idFromHttpRequest)
?|> $serializer->serializeToJson(...)
?|> fn (string $json) => new Response(status: 200, content: $json)
?? new Response(status: 404);
```

but that feels less "clean", and also note the inconsistency with `?? new
Response(status: 404)` part.

Regards,
Illia / someniatko


Re: [PHP-DEV] pipes, scalar objects and on?

2023-07-17 Thread Larry Garfield
On Mon, Jul 17, 2023, at 7:07 PM, Olle Härstedt wrote:
> 2023-07-17 18:58 GMT+02:00, Larry Garfield :
>> On Mon, Jul 17, 2023, at 2:57 PM, Olle Härstedt wrote:
>>> 2023-07-17 14:25 GMT+02:00, Karoly Negyesi :
 Hi,

 I tried to read on why the pipe RFC failed but by and large I also
 failed.

 The discussion on https://github.com/php/php-src/pull/7214 is very
 short.

 https://externals.io/message/114770 is not so short but it seems not to
 cover the latest version which uses first class functions?

 Could someone please give me a summary why it failed? I really would
 like
 to see it succeed :) I am writing code if not daily but certainly weekly
 that certainly looks like a pipeline.
>>>
>>> The pipe RFC was kinda forced in before a deadline, no?
>>>
>>> My own two cents:
>>>
>>> * It's trivial to implement a pipe() function or a Pipe class
>>> * A Pipe class is better than both a function and built-in operator,
>>> since it can be configured with custom behaviour, e.g. stop or throw
>>> on empty payload, or repeat on a collection, or even with parallelism
>>> or concurrency
>>> * If I had voting rights, I'd vote in favor in a pipe operator :)
>>
>> From my recollection, there were a couple of things involved.
>>
>> 1. It was intended to pair with the PFA RFC, which didn't pass, which made
>> it a bit less compelling.
>> 2. It was close to the RFC deadline, and it seems people get squeamish
>> around that.
>> 3. Some folks wanted Hack-style pipes instead of the pipes used by every
>> other language with pipes. I've written before on why that's a worse
>> design.
>> 4. Arguments that it can be done in user space, which is not true, as I have
>> a user-space implementation and it's comparatively cumbersome and definitely
>> slower than a native operator would be.
>> 5. General "meh" attitude on FP features in general from some people.
>>
>> Side note to Olle: If you want a customizable pipe, you've just described a
>> Monad. :-)  It's literally "contextually-sensitive func concatenation."  A
>> monadic bind operator would be harder to do with PHP's weaker type system,
>> but there are ways it could be done.
>
> Mm I don't really agree with that, I think monads make sense only in
> languages which support them syntactically. A Pipe class is a very
> straight-forward construction, and the blog posts I've read about
> monads in PHP don't look pretty at all; lots of syntactic noise going
> on. But that's another discussion... :)

At its most basic:

class Foo {
  public function __construct(public readonly mixed $val) {}

  public __bind(callable $c) {
return $c($this->val);
  }
}

new Foo('beep') >>= func(...);

Where >>= is the operator that translates to "Call __bind() on the LHS object 
with the callable on the RHS."  Poof, we now have a monad operator.  This one 
is effectively the same as |> as it doesn't do anything, but you can do 
whatever you want in the __bind() method.  

But that's a separate operation from |> or func concat.  (Unless we wanted to 
implement it as an operator override for |> that an object can do, which... is 
an option.  I don't know if I like that option, but is an option.)

The implementation for all of this is fairly trivial.  It's agreeing to do it 
that is the challenge.

--Larry Garfield

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



Re: [PHP-DEV] pipes, scalar objects and on?

2023-07-17 Thread Olle Härstedt
2023-07-17 18:58 GMT+02:00, Larry Garfield :
> On Mon, Jul 17, 2023, at 2:57 PM, Olle Härstedt wrote:
>> 2023-07-17 14:25 GMT+02:00, Karoly Negyesi :
>>> Hi,
>>>
>>> I tried to read on why the pipe RFC failed but by and large I also
>>> failed.
>>>
>>> The discussion on https://github.com/php/php-src/pull/7214 is very
>>> short.
>>>
>>> https://externals.io/message/114770 is not so short but it seems not to
>>> cover the latest version which uses first class functions?
>>>
>>> Could someone please give me a summary why it failed? I really would
>>> like
>>> to see it succeed :) I am writing code if not daily but certainly weekly
>>> that certainly looks like a pipeline.
>>
>> The pipe RFC was kinda forced in before a deadline, no?
>>
>> My own two cents:
>>
>> * It's trivial to implement a pipe() function or a Pipe class
>> * A Pipe class is better than both a function and built-in operator,
>> since it can be configured with custom behaviour, e.g. stop or throw
>> on empty payload, or repeat on a collection, or even with parallelism
>> or concurrency
>> * If I had voting rights, I'd vote in favor in a pipe operator :)
>
> From my recollection, there were a couple of things involved.
>
> 1. It was intended to pair with the PFA RFC, which didn't pass, which made
> it a bit less compelling.
> 2. It was close to the RFC deadline, and it seems people get squeamish
> around that.
> 3. Some folks wanted Hack-style pipes instead of the pipes used by every
> other language with pipes. I've written before on why that's a worse
> design.
> 4. Arguments that it can be done in user space, which is not true, as I have
> a user-space implementation and it's comparatively cumbersome and definitely
> slower than a native operator would be.
> 5. General "meh" attitude on FP features in general from some people.
>
> Side note to Olle: If you want a customizable pipe, you've just described a
> Monad. :-)  It's literally "contextually-sensitive func concatenation."  A
> monadic bind operator would be harder to do with PHP's weaker type system,
> but there are ways it could be done.

Mm I don't really agree with that, I think monads make sense only in
languages which support them syntactically. A Pipe class is a very
straight-forward construction, and the blog posts I've read about
monads in PHP don't look pretty at all; lots of syntactic noise going
on. But that's another discussion... :)

Olle

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



Re: [PHP-DEV] pipes, scalar objects and on?

2023-07-17 Thread Larry Garfield
On Mon, Jul 17, 2023, at 2:57 PM, Olle Härstedt wrote:
> 2023-07-17 14:25 GMT+02:00, Karoly Negyesi :
>> Hi,
>>
>> I tried to read on why the pipe RFC failed but by and large I also failed.
>>
>> The discussion on https://github.com/php/php-src/pull/7214 is very short.
>>
>> https://externals.io/message/114770 is not so short but it seems not to
>> cover the latest version which uses first class functions?
>>
>> Could someone please give me a summary why it failed? I really would like
>> to see it succeed :) I am writing code if not daily but certainly weekly
>> that certainly looks like a pipeline.
>
> The pipe RFC was kinda forced in before a deadline, no?
>
> My own two cents:
>
> * It's trivial to implement a pipe() function or a Pipe class
> * A Pipe class is better than both a function and built-in operator,
> since it can be configured with custom behaviour, e.g. stop or throw
> on empty payload, or repeat on a collection, or even with parallelism
> or concurrency
> * If I had voting rights, I'd vote in favor in a pipe operator :)

>From my recollection, there were a couple of things involved.

1. It was intended to pair with the PFA RFC, which didn't pass, which made it a 
bit less compelling.
2. It was close to the RFC deadline, and it seems people get squeamish around 
that.
3. Some folks wanted Hack-style pipes instead of the pipes used by every other 
language with pipes. I've written before on why that's a worse design.
4. Arguments that it can be done in user space, which is not true, as I have a 
user-space implementation and it's comparatively cumbersome and definitely 
slower than a native operator would be.
5. General "meh" attitude on FP features in general from some people.

Side note to Olle: If you want a customizable pipe, you've just described a 
Monad. :-)  It's literally "contextually-sensitive func concatenation."  A 
monadic bind operator would be harder to do with PHP's weaker type system, but 
there are ways it could be done.

I'd like to bring the Pipes RFC back if I thought there was a reasonable 
potential for it to pass this time.  I would use the crap out of it myself.  
Though I've also since decided that we do need a straight up func concat 
operator as well.  (I previously thought one would be sufficient, but in 
practice I think we do want both.)

--Larry Garfield

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



Re: [PHP-DEV] pipes, scalar objects and on?

2023-07-17 Thread Olle Härstedt
2023-07-17 14:25 GMT+02:00, Karoly Negyesi :
> Hi,
>
> I tried to read on why the pipe RFC failed but by and large I also failed.
>
> The discussion on https://github.com/php/php-src/pull/7214 is very short.
>
> https://externals.io/message/114770 is not so short but it seems not to
> cover the latest version which uses first class functions?
>
> Could someone please give me a summary why it failed? I really would like
> to see it succeed :) I am writing code if not daily but certainly weekly
> that certainly looks like a pipeline.

The pipe RFC was kinda forced in before a deadline, no?

My own two cents:

* It's trivial to implement a pipe() function or a Pipe class
* A Pipe class is better than both a function and built-in operator,
since it can be configured with custom behaviour, e.g. stop or throw
on empty payload, or repeat on a collection, or even with parallelism
or concurrency
* If I had voting rights, I'd vote in favor in a pipe operator :)

Olle

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