Rob Elliot
12/08/2023, 10:56 AMfun < R> inTransaction(work: () -> R): () -> R
fun <A, R> inTransaction(work: (A) -> R): (A) -> R
fun <A, B, R> inTransaction(work: (A, B) -> R): (A, B) -> R
fun <A, B, C, R> inTransaction(work: (A, B, C) -> R): (A, B, C) -> R
// and so ad infinitum
the actual parameters & their types to work
are irrelevant, but the returned function must have the same type, and as I decorate work
in the body I want to pass all argument to it...
I suppose I'm hoping for something like:
fun <F: (_): _> inTransaction(work: F): F {
return { _ -> work(_) }
}
Robert Williams
12/08/2023, 11:47 AMYoussef Shoaib [MOD]
12/08/2023, 11:47 AMtypealias Wrapper<R> = (() -> R) -> R
fun <R> inTransaction(): Wrapper<R> = { work ->
// prepare transaction
val result = work()
// end transaction
return result
}
infix fun <R> (() -> R).wrappedWith(wrapper: Wrapper<R>): () -> R = {
wrapper {
invoke()
}
}
infix fun <T1, R> ((T1) -> R).wrappedWith(wrapper: Wrapper<R>): (T1) -> R = { t1 ->
wrapper {
invoke(t1)
}
}
infix fun <T1, T2, R> ((T1, T2) -> R).wrappedWith(wrapper: Wrapper<R>): (T1, T2) -> R = { t1, t2 ->
wrapper {
invoke(t1, t2)
}
}
infix 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)
}
}
You have to define a wrappedWith
variant for each arity, but you define that once, and you can use it for any such Wrapper-esque function.
The usage simply looks like:
myFun wrappedWith inTransaction()
Rob Elliot
12/08/2023, 11:50 AMYoussef Shoaib [MOD]
12/08/2023, 11:54 AMWout Werkman
12/13/2023, 10:33 AM