krzysztof
03/24/2023, 10:26 PMkrzysztof
03/24/2023, 10:29 PMgiantMethod(
onCallbackOne: inst::method1,
onCallbackTwo: inst::method2
)
both method1
and method2
have different arity and/or parameter typeskrzysztof
03/24/2023, 10:30 PMmethod*
is called, but still be able to pass it down to giantMethod
like so:
giantMethod(
onCallbackOne: check(inst::method1),
onCallbackTwo: check(inst::method2)
)
krzysztof
03/24/2023, 10:30 PMJimmy Zhou
03/24/2023, 10:35 PMYoussef Shoaib [MOD]
03/24/2023, 10:39 PMJimmy Zhou
03/24/2023, 10:41 PMopen suspend fun <T : Any?> giantMethod(
function: suspend () -> T?
): T? {
// add some other logic
runCatching { function() }
....
// some other logic
}
or you can use @AspectJ
then use joinPoints and annotate your method/classephemient
03/24/2023, 10:44 PMkrzysztof
03/24/2023, 10:50 PMgiantMethod(
onCallbackOne: (...args) => check(method1, args))
)
So that once logic in check
method is completed, method1
will be called with args
arguments passedephemient
03/24/2023, 10:50 PMYoussef Shoaib [MOD]
03/24/2023, 10:55 PMimport kotlin.reflect.*
typealias Wrapper<R> = (() -> R) -> R
fun <R> checker(): Wrapper<R> = { block ->
// Run some checks
require(Unit is Unit)
println("Checking")
block()
}
fun giantMethod(getter: () -> Int, setter: (Int) -> Unit) {
setter(getter() + 1)
}
var myInt = 41
fun main() {
val setter: (Int) -> Unit = { myInt = it }
giantMethod(::myInt.wrappedWith(checker()), setter.wrappedWith(checker()))
println(myInt)
}
// You'll need one wrappedWith function per arity, but that shouldn't be that big of a deal since
// you usually won't have a function bigger than 10-15 parameters.
fun <R> (() -> R).wrappedWith(wrapper: Wrapper<R>): () -> R = {
wrapper {
invoke()
}
}
fun <T1, R> ((T1) -> R).wrappedWith(wrapper: Wrapper<R>): (T1) -> R = { t1 ->
wrapper {
invoke(t1)
}
}
fun <T1, T2, R> ((T1, T2) -> R).wrappedWith(wrapper: Wrapper<R>): (T1, T2) -> R = { t1, t2 ->
wrapper {
invoke(t1, t2)
}
}
fun <T1, T2, T3, R> ((T1, T2, T3) -> R).wrappedWith(wrapper: Wrapper<R>): (T1, T2, T3) -> R = { t1, t2, t3 ->
wrapper {
invoke(t1, t2, t3)
}
}
fun <T1, T2, T3, T4, R> ((T1, T2, T3, T4) -> R).wrappedWith(wrapper: Wrapper<R>): (T1, T2, T3, T4) -> R = { t1, t2, t3, t4 ->
wrapper {
invoke(t1, t2, t3, t4)
}
}
Youssef Shoaib [MOD]
03/24/2023, 10:56 PMwrappedWith
method for every arity, but it allows you to have unlimited checker
varieties, because the checker doesn't need to know anything about the arguments of the functionephemient
03/24/2023, 10:56 PMephemient
03/24/2023, 10:56 PMkrzysztof
03/24/2023, 11:02 PMvararg arg: Any?
would cover cases for arbitrary arity, but I expected wronglyephemient
03/24/2023, 11:03 PMYoussef Shoaib [MOD]
03/24/2023, 11:08 PMFunctionN
I think). This can be easily solved with @JvmName
though. Here's an example of it working for 23 vs 24 (Playground):
import kotlin.reflect.*
typealias Wrapper<R> = (() -> R) -> R
fun <R> checker(): Wrapper<R> = { block ->
// Run some checks
require(Unit is Unit)
println("Checking")
block()
}
fun giantMethod(getter: (Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int) -> Int,
setter: (Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int) -> Unit) {
setter(getter(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) + 1,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
}
var myInt = 41
fun main() {
// 23 args
val getter: (Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int) -> Int =
{ _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _ ->
myInt
}
// 24 args
val setter: (Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int) -> Unit =
{ it, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _ ->
myInt = it
}
giantMethod(getter.wrappedWith(checker()), setter.wrappedWith(checker()))
println(myInt)
}
// 23
@JvmName("wrappedWith23")
fun <T, R> ((T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T) -> R).wrappedWith(wrapper: Wrapper<R>): (T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T) -> R =
{ t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14, t15, t16, t17, t18, t19, t20, t21, t22, t23 ->
wrapper {
invoke(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14, t15, t16, t17, t18, t19, t20, t21, t22, t23)
}
}
// 24
@JvmName("wrappedWith24")
fun <T, R> ((T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T) -> R).wrappedWith(wrapper: Wrapper<R>): (T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T) -> R =
{ t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14, t15, t16, t17, t18, t19, t20, t21, t22, t23, t24 ->
wrapper {
invoke(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14, t15, t16, t17, t18, t19, t20, t21, t22, t23, t24)
}
}
ephemient
03/24/2023, 11:09 PMephemient
03/24/2023, 11:12 PMsuspend fun <T1...T21, R> wrapper(block: suspend (T1...T21) -> R): suspend (T1..T21) -> R
etc. overloads, you run into the issue a little earlierkrzysztof
03/24/2023, 11:24 PM