Closed SGrondin closed 8 months ago
Hi @SGrondin, thanks for the detailed issue.
Something like this sounds useful to me, as you said, for that smaller amount of the time you might want to do something different in the case that both fibers succeed simultaneously. Without extending fibres to support this, I can't think of a solution that doesn't involve lifting into Eio promises so it seems like a good idea.
It also reminds me a bit of nchoose_split
which I needed for a port of vpnkit although that's at the promise-level (in the Eio sense), but that's orthogonal to having this in the Fiber API. Just adding that as the issue jogged my memory.
Yes, something like this sounds useful. I'd been wondering about having an optional combine
argument for this case. e.g. something like:
val first : ?combine:('a -> 'a -> 'a) -> (unit -> 'a) -> (unit -> 'a) -> 'a
So if we get an additional value while waiting for things to cancel, it does combine acc x
to merge it in. The current behaviour would be equivalent to ~combine:fst
.
Having a separate function and returning a list might be simpler, though.
What are you planning to use it for?
These are a few real world Eio examples where I've used Lwt.npick
in the past:
Eio_unix.sleep
finishes, I'd still want to process the task resultI like your idea! ~combine
is more flexible than my Fiber.n_first
suggestion, but I think it's probably even more important to add this feature to Fiber.any
(where I think a separate function like Fiber.n_any
might make more sense than a ~combine
reducer).
Addressed by #587
Motivation
Under
Fiber.first
:This enables
Fiber.first
to have a nice, convenient API. 98% of the time, I do not care about the edge case, so the benefits of the API are worth the downside explained in the warning.But 2% of the time, I do care about the return value of the second fiber that may also have succeeded.
Comparison: Lwt
Lwt.pick
This function is roughly equivalent to
Fiber.any
.Lwt.npick
Draft idea
We're optimizing for the 2% case here. Something that behaves just like
Fiber.first
, but without losing the second successful result (when it succeeds """at the same time""").The way Lwt accomplishes this is by scanning the list for other successful promises before resolving the returned promise.
I had a quick look at the code and it seems doable.
Is this a feature the maintainers would welcome?