Not to mention that doesn't compile either... To actually get it to compile, I need to define the closure type in the calling function's (or impl's) type definitions.
Anyway. This is pretty hideous, and I was wondering if anyone else has come up with an elegant solution for this kind of situation.
I should also mention, that I understand the compiler needs to know the type of the parameter to generate code for the side of the branch when the Option isn't None, but I'd be happy with a solution that compile-time specialized the function into a version that totally omitted the non-None branches. But I couldn't figure out the right way to do that without some really ugly macros.
Thank you! My mistake was using Fn instead of fn in my type definition for my_none. Thank you!
Still hoping there is a way to compile-time specialize the function for the absence of an argument.
But I wonder if the way you've made the argument const results in the compiler potentially taking the liberty. Still make the call ugly, but perhaps just as efficient. Haven't look at the ASM yst.
So I've been playing with this a bit more, and I was getting more comfortable with the not-so-ugly solution @quinedot proposed of having a const declared that casual users could just pass in without thinking about it.
And all seemed well in the world until I tried to move the declaration of the const into a library. Now, presumably because of dynamic linking, I'm getting cannot infer type errors.
Equally troubling, this also hints that the compiler won't be able to optimize away the const if it's part of a separate binary object.
I'll just write a wrapper function without the optional arg. Then the caller can call the appropriate entry point depending on the functionality they want. Some people might say that's cleaner anyway.
Instead of making the closure optional, you could also provide a nop or identity function to use as the argument when users don’t need any special behavior— Then your wrapper function becomes a trivial 1-line convenience function.
Thanks for the reply. I tried that, but the trouble is that the closure's return type is a generic. So the no-op function needs to be specialized by the compiler, even though it ultimately doesn't matter.
So in practice I ended up in exactly the same boat of "cannot infer type" errors.
But if the closure’s return type is generic, then it’s caller-specified, and your example function always returns (). What is the effective return type of the closure if the user passes in None?
It works great when it's all in one file. But as soon as the no-op closure is imported from a library (the same library that contains the function I'm passing the closure to), the calling code won't compile because it complains the type isn't known.
Because the closure specifies its own return type, the nop you supply needs to use a concrete return type to avoid type inference failures; there’s no other place that information could come from.
To repeat my pattern presented in this answer, a zero-sized option using an uninhabited function type appears to be an elegant solution to me. This will guaranteed not generate any non-None branches anymore.