Just found myself writing these… ```fun Runnable.toFun(): () -> Unit = { this.run() } fun Functio...
r
Just found myself writing these…
Copy code
fun 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?
s
why would you do this?
r
To convert back and forward between kotlin functions and Runnable / Callable.
s
What's the use case of this? Is there any particular library requires you do this?
r
I’m writing an implementation of
ExecutorService
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.
s
Avoiding repetition in the implementation requires using kotlin functions.
Could you explain more about this?
with SAM conversion you can just use Runnable interface in your kotlin code as in Java world.
n
btw you can say say
((T) -> Unit)
instead of
Function0<T>
I believe
r
For me this does not compile:
Copy code
class Foo {
  fun takesFunction(task: () -> Unit) = task()
  fun takesRunnable(task: Runnable) = takesFunction(task)
}
s
just use
Runnable
is fine I guess? you can write the following
Copy code
fun foo(fn: Runnable) = fn.run()
    fun bar() = foo { TODO() }
r
OK, there is a simpler way using method references:
Copy code
override fun execute(command: Runnable) = foo(command::run)
override fun <T> submit(task: Callable<T>) = foo(task::call)
private fun foo(task: () -> T) = TODO()
Harder is coercing in a
map
call…
Copy code
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:
Copy code
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.
(And of course you can’t inline coerce either, which is the sort of thing which must bring Haskell programmers out in hives…)
n
Couldn't you define your own interface that inherits from runnable/callable
and makes the run/call function,
interface
hmm maybe the conversion only goes the other way. I thought that SAMs covered this case but I must just be confused.
Okay, so it looks like even if you don't control Runnable/Callable, you can define your own interfaces beneath them, and make things a little nicer
Copy code
interface Runnable {
    fun bar()
}

fun interface RunnableSam : Runnable {
    override fun bar()
}

fun accepts(x: RunnableSam) {}

fun main() { 
   accepts( { } )
}
r
I’m implementing an interface I don’t control whose methods accept Runnable and Callable
n
yeah, not much you can do then
r
FWIW it eventually occurred to me that I was better off creating a new
interface 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
.
But until that occurred to me, this is where I’d got to: https://gist.github.com/Mahoney/a8208dcbf97e0bd0d0002ef4cee892d2