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