JuliaLang/julia

[RFC] Type stable wrapper for arbitrary callables

yuyichao opened this issue · 2 comments

The idea is to have an equivalent of function pointer in C or std::function in C++11. This could be useful to avoid over specialization (Ref #13412 (comment)) and also for implementing mutable callback list/table. In these cases, it is acceptable that the callback function is not/cannot be inlined to the caller but it is also desired to avoid necessary boxing or runtime type check/dispatch.

One way to implement something like this is to use cfunction. I've hacked together a proof of concept implementation here. It is very non-generic and is not ideal due to the limitations of cfunction (no vararg, no way to bypass type checks, for example). Nevertheless, the benchmark comparing calling two functors stored in a Union array and an array with this wrapper shows that calling with the wrapper is ~40 times faster and avoids the necessary boxing of the arguments and results.

A few features that I think should be included:

  • Allow non-leaf types as arguments and results (not sure about Vararg)
  • Allow ignoring the results
  • Allow conversion/type assertion on the result if type inference cannot figure out the return type of the function (instead of erroring out like cfunction)

@JeffBezanson Is there anything related that is planed / implemented for #13412 ?

I'd like to advocate for this being in stdlib sooner rather than later, my arguments are as follows:

  • The functionality offered by FunctionWrappers is not otherwise available in the language. As far as I know there are no shortcuts, cheats or hacks to get this kind of efficient unboxing of functions by "straightforward" means.
  • Very few people would have the expertise to write or maintain this (certainly not me), so if you decide that you need it and are not aware of the package you are probably pretty screwed. If the package doesn't get updated for a new version of Julia you are likewise screwed.

I know it has been stated repeatedly that this is experimental, but it certainly already offers quite a bit of functionality which, again, is otherwise unobtainable.

Any interest in doing this? Any ideas what else would be required? (I wish I could offer to be more helpful, but this is well beyond my expertise.)

I recently had the need for this and totally support the idea. Cool stuff 👍