Kotlin中的条件副作用和可选类型

Grz*_*rek 5 side-effects kotlin

我试图在Kotlin中执行一个简单的副作用:

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

        service.run(...)
    }
}
Run Code Online (Sandbox Code Playgroud)

如您所见,当存储库返回非空值并满足someCondition时,应执行副作用.

是否有任何Kotlin方式这样做而不是使用if {} - 返回构造?

在Java 8中,它可以通过以下方式实现:

optional
  .filter(...)
  .ifPresent(...)  
Run Code Online (Sandbox Code Playgroud)

Yoa*_*erg 5

更新: 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
Run Code Online (Sandbox Code Playgroud)

您可以通过以下方式使用它:

repository.findByUID(request.userId)?.takeIf { someCondition }?.let { service -> }
Run Code Online (Sandbox Code Playgroud)

Kotlin在stdlib中不包含此类方法。

但是,您可以定义它:

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

使用此方法,您的示例可以重写为:

fun handle(request: Request) {
    repository.findByUID(request.userId)?.ifPresent { someCondition }?.let {
        service.run(...)
    }
}
Run Code Online (Sandbox Code Playgroud)

另一种选择是使用内置的扩展列表(但使用列表会产生开销):

listOf(repository.findByUID(userId)).filter { someCondition }.forEach { service.run(...) }
Run Code Online (Sandbox Code Playgroud)


mfu*_*n26 5

Kotlin的可空类型与Java的Optional非常相似(与Guava的Optional非常相似).

在Kotlin 1.1中,您可以使用takeIf"就像filter单个值"(takeIf()和() - Kotlin 1.1中的新功能 - Kotlin编程语言):

repository.findByUID(request.userId).takeIf { !someCondition }?.let { service.run(...) }
Run Code Online (Sandbox Code Playgroud)

科特林1.0没有定义map,flatMap,filter/ takeIf等,为可空类型,但你可以很容易地定义自己的函数.例如:

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

用法示例:

filter(repository.findByUID(request.userId)) { !someCondition }?.let { service.run(...) }
Run Code Online (Sandbox Code Playgroud)