Let's say I wanted to write a concurrency function that takes N functions as input, calls them concurrently, and waits for all of them to finish. Like std::thread::spawn
, but for when there are a fixed number of functions and I don't need to spawn them incrementally. In theory I think I can accept them like this:
fn fan_out(_fns: &[&dyn Fn()]) {
todo!();
}
However, in practice it seems it's not possible to call this conveniently unless all of the functions have the same type underneath. For example, this doesn't work because each input is not already a &dyn Fn()
:
fan_out(&[
|| println!("taco"),
|| println!("burrito"),
]);
…and then also probably later I'd get a compiler error about how they have different types because of course you can't have an array of disparate types.
Is there any way to structure this so I can have approximately that syntax when calling fan_out
? In C++ for example I'd be able to do the following, since the lambdas implicitly convert to std::function<void()>
:
void FanOut(std::vector<std::function<void()>> fns);
FanOut({
[] { std::cout << "taco\n"; },
[] { std::cout << "burrito\n"; },
});
This doesn't work because a closure doesn't automatically coerce to &dyn Fn()
. You have to take a reference to it. This isn't even unique to closures, this is common to all &dyn _
types -- impl Foo
never automatically coerces to &dyn Foo
, but &impl Foo
can.
That is, while this does not compile:
fan_out(&[|| println!("taco"), || println!("burrito")]);
This does:
fan_out(&[&|| println!("taco"), &|| println!("burrito")]);
To me this seems to qualify as "approximately that syntax."