Is there any way of wrapping arbitrary functions? ...
# getting-started
w
Is there any way of wrapping arbitrary functions? I want do something like
Copy code
class FunctionWrapper<T: Function<Unit>>(val fn: T){
  fun invokeWithLogging(some_args: T.Arguments) {
    // some logging here
    fn.invoke(some_args)
  }
}
But that's not valid Kotlin before I don't think you can get the type of a generic function's arguments, and even less declare/invoke functions in that matter. Any thoughts?
y
Would the logging need to involve the function's arguments? If not, here's a
Wrapper
type I wrote a while back that allows you to wrap arbitrary functions in a type-safe manner, with the caveat that its
wrappedWith
functions have to be written for every arity. https://kotlinlang.slack.com/archives/C0B8MA7FA/p1679698518922679?thread_ts=1679696808.337589&amp;cid=C0B8MA7FA If you need the function's arguments, it's trivial to modify the code to include passing an
Array<Any?>
that has the function's arguments to the
wrapper
. Note that this is likely to impact performance (due to array creation and boxing etc)
w
ah, that's very helpful - thanks! (no, we don't need the function arguments for this use case, but good to have a strategy for that if we need it)
y
The code should be very extensible to allow any use-case, really. You'll just have to write (or likely generate with a simple string template) the
wrappedWith
functions.
e
an approach like https://github.com/Foso/Cabret-Log would also work for logging function parameters
a compiler plugin is definitely overkill for most purposes though, I wouldn't do that if you have other options
(if targeting jvm/android only, I'd choose to perform bytecode manipulation like https://github.com/sephiroth74/AndroidDebugLog instead of a compiler plugin since it's more stable, but either way, if you can do it in plain code it's much more straightforward)
s
If you're Kotlin code backend is the JVM you could fallback to using Java libs: https://www.baeldung.com/aspectj though it'd be to heavy of an approach for me (should you use Spring, then AspectJ is already included though).