Rob Elliot
04/01/2021, 7:07 PMfun Runnable.toFun(): () -> Unit = { this.run() }
fun Function0<Unit>.toRunnable(): Runnable = Runnable { this() }
fun <T> Callable<T>.toFun(): () -> T = { this.call() }
fun <T> Function0<T>.toCallable(): Callable<T> = Callable { this() }
and then wondered a) do they already exist or b) is there a better way?Sola
04/01/2021, 7:25 PMRob Elliot
04/01/2021, 7:25 PMSola
04/01/2021, 7:29 PMRob Elliot
04/01/2021, 7:33 PMExecutorService
that maintains an SLF4J MDC
in the asynchronous tasks. ExecutorService
accepts Runnable
and Callable<T>
. Avoiding repetition in the implementation requires using kotlin functions. The net result is I need to convert backwards and forwards between () -> Unit
and Runnable
, and between () -> T
and Callable<T>
, and it’s more legible if I don’t keep nesting curly braces.Sola
04/01/2021, 7:37 PMAvoiding repetition in the implementation requires using kotlin functions.Could you explain more about this?
Sola
04/01/2021, 7:38 PMnanodeath
04/01/2021, 7:53 PM((T) -> Unit)
instead of Function0<T>
I believeRob Elliot
04/01/2021, 7:53 PMclass Foo {
fun takesFunction(task: () -> Unit) = task()
fun takesRunnable(task: Runnable) = takesFunction(task)
}
Sola
04/01/2021, 7:54 PMRunnable
is fine I guess?
you can write the following
fun foo(fn: Runnable) = fn.run()
fun bar() = foo { TODO() }
Rob Elliot
04/01/2021, 8:13 PMoverride fun execute(command: Runnable) = foo(command::run)
override fun <T> submit(task: Callable<T>) = foo(task::call)
private fun foo(task: () -> T) = TODO()
Rob Elliot
04/01/2021, 8:27 PMmap
call…
override fun <T> invokeAll(tasks: Collection<out Callable<T>>): List<Future<T>> {
val wrappedTasks = tasks.map { task -> foo(task::call) }
delegate.invokeAll(wrappedTasks) // does not compile, List<() -> T> is not a Collection<out Callable<T>>
}
private fun <T> foo(task: () -> T): () -> T = TODO()
You can trick the compiler with an identity method:
override fun <T> invokeAll(tasks: Collection<out Callable<T>>): List<Future<T>> {
val wrappedTasks = tasks.map { task -> coerce(foo(task::call)) }
delegate.invokeAll(wrappedTasks) // compiles!
}
private fun <T> coerce(callable: Callable<T>) = callable
private fun <T> foo(task: () -> T): () -> T = TODO()
Interestingly you cannot change coerce
to make Callable<T>
the receiver, it then stops compiling.Rob Elliot
04/01/2021, 8:52 PMNir
04/01/2021, 8:56 PMNir
04/01/2021, 8:57 PMinterface
Nir
04/01/2021, 8:59 PMNir
04/01/2021, 9:02 PMNir
04/01/2021, 9:03 PMinterface Runnable {
fun bar()
}
fun interface RunnableSam : Runnable {
override fun bar()
}
fun accepts(x: RunnableSam) {}
fun main() {
accepts( { } )
}
Rob Elliot
04/01/2021, 9:26 PMNir
04/01/2021, 9:30 PMRob Elliot
04/06/2021, 10:16 AMinterface KExecutorService
with a single fun <T> submit(task: () -> T): Future<T>
and a trivial adapter implementation that delegates to a java.util.ExecutorService
. Then writing a decorator to do things around the function call became trivial without having to worry about Runnable
and Callable
.Rob Elliot
04/06/2021, 5:07 PM