On Sat, Mar 8, 2025, at 09:06, Eugene Sidelnyk wrote:
>>
>
>> The uncoloring of functions in PHP is probably one of the most annoying aspects of fibers,
>> IMHO. It's hard to explain unless you've been using them awhile. But, with colored
>> functions, the caller has control over when the result is waiting on -- it could be now, it could be
>> in a totally different part of the program, or not at all. With fibers, the author of the function
>> you are calling has control over when the result is waited on (and they don't have control over
>> anything they call). This can create unpredictable issues when writing code where a specific part
>> wrote some code thinking it had exclusive access to a property/variable. However, someone else
>> changed one of the functions being called into an async function, making that assumption no longer
>> true.
>>
>> With colored functions, the person making changes also has to update all the places where
>> it is called and can validate any assumptions are still going to be true; uncolored functions means
>> they almost never do this. This results in more work for people implementing async, but more correct
>> programs overall.
>>
>> But back to the awaiting on results. Say I want to read 10 files:
>>
>> for ($i = 0; $i < 10; $i++) $results[] = file_get_contents($file[$i]);
>>
>> Right now, we have to read each file, one at a time, because this is synchronous. Even with
>> this RFC and being in a fiber, the overall execution might be non-blocking, but the code still reads
>> one file after another sequentially. Fibers do not change this.
>>
>> With this RFC (in its original form), we will be able to change it so that we can run it
>> asynchronously though and choose when to wait:
>>
>> for($i = 0; $i < 10; $i++) $results[] = async\async(fn($f) => file_get_contents($f),
>> $file[$i]);
>> // convert $results into futures somehow -- though actually doesn't look like it is
>> possible.
>> $results = async\awaitAll($results);
>>
>> In that example, we are deliberately starting to read all 10 files at the same time. If we
>> had colored functions (aka, async/await) then changing file_get_contents to async would mean you
>> have to change everywhere it is called too. That means I would see that file_get_contents is
>> synchronous and be able to optimize it without having to even understand the reasoning (in most
>> cases). I was a user of C# when this happened to C#, and it was a pain... So, at least with PHP
>> fibers, this won't be AS painful, but you still have to do some work to take full advantage of
>> them.
>>
>> I kind of like the idea of a nursery for async, as we could then update
>> file_get_content's return type to something like string|false|future<string|false>. In
>> non-async, you have everything behave as normal, but inside a nursery, it returns a future that can
>> be awaited however you want and is fully non-blocking. In other words, simply returning a future is
>> enough for the engine to realize it should spawn a fiber (similar to how using yield works with
>> generators).
>>
>> In any case, I believe that a nursery requires the use of colored functions. That may be
>> good or bad, but IMHO makes it much more useful and easier to write correct and fast code.
>>
>
>
> In my opinion, colored functions is the worst thing that could happen to PHP.
>
> https://journal.stuffwithstuff.com/2015/02/01/what-color-is-your-function
> Describes quite expressively what's wrong about this approach.
>
> As the result, you will make everything async.
> Want a repository? It will be all async.
> Want a logger? Also async.
> Need to cache something? Make it async.
>
> This is going to be a ton of changes, when currently sync (blue function) will have to become
> async (red one).
>
> The way amphp goes - it's the right way. They have had this problem of red-blue functions
> a long ago until Fibers came into place.
>
> What they used until third version is generator-based coroutines, so that instead of returning
> actual object, you spoil the signature of the function and return generator that will return that
> object (iow, "Promise").
>
> This is just annoying, and IMO should not be considered.
My point in the email is that this happens anyway. With colored functions, you /*always/* decide how
to handle async. Which, as you mentioned, can be annoying. With uncolored functions, you */never/*
get to decide unless you wrap it in a specific form (async\run or async\async, in this RFC), which
ironically colors the function. I can't think of any way around it. My biggest issue with this
RFC is that it results in **multiple** colors: FiberHandle, Future, and Resume.
— Rob