Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

339
Visualizações
How can I check if a set of functions all return non null, in a single expression?

Suppose I have three functions foo, bar, baz, all of which return nullable types.

fun foo(): Int? = 1
fun bar(): Int? = 2
fun baz(): Int? = 3

I want to call them, and if all them returns non-null, I want to compute a value from their return values.

I could do this with statements, like this:

val x = foo()
val y = bar()
val z = baz()
val result = if (x != null && y != null && z != null) x + y + z else null

However, I don't like the fact that I have to declare 3 extra variables that I can still access afterwards. By having 3 extra statements like this, it also means that I cannot use expression-bodied functions, if I were writing a function that returns result.

If I use lets instead:

val result = foo()?.let { x -> 
    bar()?.let { y -> 
        baz()?.let { z -> 
            x + y + z
        } 
    } 
}

This creates a deep nesting. If it were only one function, this would have been fine, but with 3 functions or more, this makes my intention of "call these three functions, if they are all non null, add them together" rather unclear.

How can I write this in a way that clearly conveys my intention, but also making it a single expression?

over 4 years ago · Santiago Trujillo
3 Respostas
Responde à pergunta

0

val result = listOf(foo(), bar(), baz())
  .reduce { acc, i ->
    when {
      acc == null || i == null -> null
      else                     -> acc + i
    }
  }

Or as function:

fun <T> apply(operation: (T, T) -> T, vararg values: T?): T? {
  return values
    .reduce { acc, i ->
      when {
        acc == null || i == null -> null
        else                     -> operation(acc, i)
      }
    }
}

val result = apply({ x, y -> x + y }, foo(), bar(), baz())
over 4 years ago · Santiago Trujillo Relatório

0

You could filter out all null-values and only apply an operation on the list, if it did not shrink in size, e.g.:

fun sumIfNoneNull(values: List<Int?>): Int? = values
    .filterNotNull()
    .takeIf { it.size == values.size }
    ?.sum()

One may generalize this further, e.g.:

fun <T, R> List<T>.foldIfNoneNull(
    initial: R,
    operation: (acc: R, T) -> R
): R? = this
    .filterNotNull()
    .takeIf { nonNullList -> nonNullList.size == this.size }
    ?.fold(initial, operation)

You may use this like any other fold, e.g.:

listOf(foo(), bar(), baz()).foldIfNoneNull(0) { acc, cur -> acc + cur }
over 4 years ago · Santiago Trujillo Relatório

0

If they are of different types, I think you need to write your own helper functions like these (different overloads needed for different numbers of parameters, because there's no other way for the compiler to know the types of the arguments):

inline fun <T : Any, U : Any, R> ifAllNotNull(t: T?, u: U?, block: (t: T, u: U) -> R): R? {
    return when {
        t != null && u != null -> block(t, u)
        else -> null
    }
}

inline fun <T : Any, U : Any, V : Any, R> ifAllNotNull(t: T?, u: U?, v: V?, block: (t: T, u: U, v: V) -> R): R? {
    return when {
        t != null && u != null && v != null -> block(t, u, v)
        else -> null
    }
}
val result = ifAllNotNull(foo(), bar(), baz()) { x, y, z -> x + y + z }

Note that all three parameters will be evaluated before any are checked for null.


Or if you want to do what you described (hiding the three variables after the result calculation) using just standard library functions, you can use run to limit the scope of the temporary variables:

val result = run {
    val x = foo()
    val y = bar()
    val z = baz()
    if (x != null && y != null && z != null) x + y + z else null
}

This would also give you the opportunity to short-circuit if you like:

val result = run {
    val x = foo() ?: return@run null
    val y = bar() ?: return@run null
    val z = baz() ?: return@run null
    x + y + z
}
over 4 years ago · Santiago Trujillo Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda