2016-12-28 4 views
4

Я пытаюсь выполнить простой побочный эффект в Котлин:Условные побочные эффекты и дополнительные типы в Котлин

fun handle(request: Request) { 
    repository.findByUID(request.userId)?.let { 
     if (someCondition) return 

     service.run(...) 
    } 
} 

Как вы можете видеть, как побочный эффект должен быть выполнен, когда возвращается хранилище ненулевое значение и когда someCondition выполнено.

Есть ли способ Kotlin сделать это, а не использовать if {} - return constructs?

В Java 8, это может быть достигнуто за счет:

optional 
    .filter(...) 
    .ifPresent(...) 
+0

Используйте 'if's, сделать ядро ​​более ясным: D – voddan

ответ

3

Update: Kotlin 1.1 имеет метод, называемый takeIf:

/** 
* Returns `this` value if it satisfies the given [predicate] or `null`, if it doesn't. 
*/ 
@kotlin.internal.InlineOnly 
@SinceKotlin("1.1") 
public inline fun <T> T.takeIf(predicate: (T) -> Boolean): T? = if (predicate(this)) this else null 

Вы можете использовать его таким образом:

repository.findByUID(request.userId)?.takeIf { someCondition }?.let { service -> } 

Kotlin не содержит такого метода в stdlib.

Однако, Вы можете определить его:

inline fun <K : Any> K.ifPresent(condition: K.() -> Boolean): K? = if (condition()) this else null 

Используя этот метод, ваш пример можно переписать в виде:

fun handle(request: Request) { 
    repository.findByUID(request.userId)?.ifPresent { someCondition }?.let { 
     service.run(...) 
    } 
} 

Другим вариантом может быть использование встроенной в расширениях для списка (но это накладные расходы с использованием списков):

listOf(repository.findByUID(userId)).filter { someCondition }.forEach { service.run(...) } 
4

Котлин-х nullable types очень похожи к Java Optional (который очень похож на Guava Optional).

Котлин 1.1 вы можете использовать takeIf, который "походит filter для одного значения" (takeIf() and also() - What's New in Kotlin 1.1 - Kotlin Programming Language):

repository.findByUID(request.userId).takeIf { !someCondition }?.let { service.run(...) } 

В Котлин 1.0 не определяет map, flatMap, filter и т.д. для обнуляемого типов, но вы может легко определить вашу собственную функцию. например:

inline fun <T> filter(value: T?, predicate: (T) -> Boolean): T? { 
    return if (value != null && predicate(value)) value else null 
} 

Пример использование:

filter(repository.findByUID(request.userId)) { !someCondition }?.let { service.run(...) } 
+0

Хорошо, спасибо. Я надеялся на встроенное решение, но думаю, мне нужно его самостоятельно создать :) –

+1

Возможно, вы сможете сделать его встроенным: https://kotlinlang.org/contribute.html – mfulton26

+0

Идеологически «нуль» Котлина очень отличается от «Оптиналь». У этого нет бизнеса с 'map' и' filter' IMO – voddan

0

я бы без лишней LIBS ни функций расширения с этой конструкцией:

?.let { if (someCondition) null else it } 

После применяют указанные эта конструкцию на примере коды из исходного вопроса , это будет выглядеть так:

Или, по крайней мере, это выглядит нормально, компилирует и имеют одинаковые типы в моем коде после определения Request, repository, findByUid и т.д. :-)

Смежные вопросы