Идиоматический способ вернуть значение из лямбды в Котлин - PullRequest
1 голос
/ 11 июля 2019

У меня есть функция, которая возвращает некоторый результат, и я также измеряю время работы этой функции:

private suspend fun <T> runParallelTasksWithStatistics(
    chunksOfParallelTasks: List<List<T>>,
    task: suspend (SessionId?, ClientApiRpcProxy, T) -> Unit
): StressTestStatistics {
    val testStartTimeMs = System.currentTimeMillis()
    val taskResults = runParallelTasks(chunksOfParallelTasks, task)
    val totalMillisPassed = System.currentTimeMillis() - testStartTimeMs

    return calculateStressTestStatistics(
        AggregateTaskResults(taskResults, totalMillisPassed)
    )
}

Как видите, после запуска функции runParallelTasks(chunksOfParallelTasks, task) мне нужно два значения:

  1. totalMillisPassed
  2. taskResults

Как я могу использовать measureTimeMillis, не прибегая к изменению var переменной?

val totalMillisPassed = measureTimeMillis {
    val taskResults = runParallelTasks(chunksOfParallelTasks, task)
}

AggregateTaskResults(taskResults, totalMillisPassed)

В области AggregateTaskResults() я вижу только totalMillisPassed, но я также хочу получить доступ к результату taskResults.

Ответы [ 2 ]

2 голосов
/ 11 июля 2019

Альтернатива ответу Тоддса, но реализация собственной функции:

inline fun <T> measureTimeMillis(handleDuration: (Long) -> Unit = { }, supplier: () -> T): T {
    val start = System.currentTimeMillis()
    return supplier().also {
        handleDuration(System.currentTimeMillis() - start)
    }
}

Использование выглядит следующим образом:

val result = measureTimeMillis {
   // your function
}

или если вы хотите сделать что-то еще сduration:

val result = measureTimeMillis(::registerDuration) {
   // your function
}
val result = measureTimeMillis( { println("Took $it ms") } ) {
   // your function
}

Чтобы вы не запутались со стандартной функцией, возможно, вам пригодится другое имя.

Для этого я создал свой собственный тип обертки меры, так что я легковозможность улучшить некоторые выражения с помощью моего измерителя по умолчанию (который регистрирует или печатает или что-то еще).Если я хочу измерить что-то, я просто добавляю measurer measure (использовал для него infix) перед строкой или перед присваиванием, чтобы не нужно было обрабатывать возвращенные миллисекунды на измерение.

2 голосов
/ 11 июля 2019

Вы можете определить свою собственную версию measureTimeMilis, которая возвращает время и результат:

fun <R> measureTimeMillisWithResult(block: () -> R): Pair<Long, R> {
    val start = System.currentTimeMillis()
    val result = block()
    return Pair(System.currentTimeMillis() - start, result)
}

И, чтобы назвать его, вы можете воспользоваться тем, что Pair может быть разрушено:

val (time, result) = measureTimeMillisWithResult {
    // Calculate the result here.
}
println("Calculation took $time ms")
return result
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...