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

我正在努力在Kotlin中执行一个简单的副作用:

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

正如你所看到的那样,当知识库返回一个非空值并且满足someCondition时,应该执行副作用

有没有Kotlin这样做的方式,而不是使用如果{} – 返回结构?

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

 optional .filter(...) .ifPresent(...) 

更新: 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(...) } 

Kotlin的可空类型与Java的可选 类型非常相似(与Guava的可选 类型非常相似)。

Kotlin 1.1可以使用takeIf ,“就像filter一个单一的值”( takeIf()和also() – Kotlin 1.1中的新功能 – Kotlin编程语言 ):

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

在Kotlin 1.0中没有定义mapflatMapfilter等可为空类型,但可以轻松定义自己的函数。 例如:

 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(...) } 

我会去没有额外的库,也没有扩展功能这个结构:

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

在原始问题的代码样本上添加这个构造之后,它将如下所示:

 fun handle(request: Request) { repository.findByUID(request.userId) ?.let { if (someCondition) null else it } ?.let { service.run { /* ... */ } } } 

或者至少它看起来findByUid ,在定义了RequestrepositoryfindByUid等之后,在我的代码库中编译并具有相同的类型:-)