Efectos secundarios condicionales y types opcionales en Kotlin

Estoy tratando de realizar un efecto secundario simple en Kotlin:

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

Como puede ver, el efecto secundario se debe realizar cuando el repository devuelve un valor no nulo y cuando se cumple alguna condición .

¿Hay alguna forma de Kotlin de hacer esto en lugar de usar if {} – devolver constructos?

En Java 8, podría lograrse mediante:

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

Actualización: Kotlin 1.1 tiene un método llamado takeIf :

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

Puedes usarlo de esta manera:

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

Kotlin no contiene dicho método en el stdlib.

Sin embargo, puedes definirlo:

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

Usando este método, su ejemplo puede ser reescrito como:

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

Otra opción puede ser usar las extensiones integradas para la list (pero hay una sobrecarga de usar lists):

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

Los types anulables de Kotlin son muy similares a los opcionales de Java (que es muy similar a la opción de Guava).

Kotlin 1.1 puede usar takeIf que "es como filter para un solo valor" ( takeIf () y también () – Novedades de Kotlin 1.1 – Kotlin Programming Language ):

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

En Kotlin 1.0 no se define map , flatMap , filter , etc. para types anulables, pero puede definir fácilmente su propia function. p.ej:

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

Ejemplo de uso:

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

Me gustaría ir sin libs adicionales ni funciones de extensión con esta construcción:

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

Después de aplicar este constructo en el ejemplo de código de la pregunta original, se vería así:

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

O al less se ve bien, comstack y tiene los mismos types en mi base de código después de definir Request , repository , findByUid , etc. 🙂