1
votes

Quelle est la manière la plus lisible de faire la somme de deux Int nullables dans Kotlin?

J'ai essayé de faire quelque chose comme ce qui suit:

val result = biLet(a, b) { p1, p2 -> p1 + p2 }

mais il ne compile pas car plus attend un Int .

J'ai également essayé de créer une fonction biLet:

fun <V1, V2, V3> biLet(a: V1?, b: V2?, block: (V1, V2) -> V3): V3? {
    return a?.let {
        b?.let { block(a, b) }
    }
}

et utilisez-le comme ça:

val a: Int? = 1
val b: Int? = 1

a?.plus(b)

mais cela semble beaucoup de travail pour quelque chose d'apparemment simple. Existe-t-il une solution plus simple?


3 commentaires

b?.let {a?.plus(it)} fonctionne


J'ai déplacé mon commentaire vers l'une des réponses. Ce que je veux dire, c'est que si je vois val c = a + b pour deux Int s nullables, ce n'est pas évident si c est nullable, et ce n'est pas évident ce qui se passe si a ou b est nullable. Peut-être que l'opérateur + les rend par défaut à 0 quand nul, ou peut-être à -1 , ou peut-être même qu'il lève une IllegalArgumentException. Peut-être qu'il renvoie simplement 0 si l'un ou l'autre des nombres est null . Ce sont tous des comportements éventuellement souhaités en fonction du contexte. Mais s'il s'agit d'une petite classe et que la fonction d'opérateur est gardée privée pour la classe, ce n'est pas grave.


Logique. Je ne suis pas au courant d'une théorie sur les types Nullable qui définit les opérations. Je considérerais raisonnable de définir toute opération entre les types Nullable comme ayant un résultat nul si les deux opérandes sont Null.


3 Réponses :


7
votes

Malheureusement, il n'y a déjà rien dans la bibliothèque standard pour additionner deux entiers nullables.

Ce que vous pouvez faire, cependant, est de créer un operator fun pour un Int? nullable Int? :

val a: Int? = 2
val b: Int? = 3
val c = a + b

Et puis, vous pouvez l'utiliser normalement comme la version non nulle:

operator fun Int?.plus(other: Int?): Int? = if (this != null && other != null) this + other else null

Si vous ne souhaitez pas créer de fonction pour lui, vous pouvez toujours utiliser son corps pour gérer la possibilité de nullité des deux entiers.


0 commentaires

3
votes

Eh bien, pour moi, celui-ci a l'air le plus lisible,

val result = (a?:0)+(b?:0)

Et quand l'un est nul, l'autre n'est pas nul et que vous voulez juste la valeur non nulle, alors peut-être comme ceci:

val result = if (a != null && b != null) a+b else null


5 commentaires

PS: le second sera égal à 0 si les deux étaient nuls.


C'est certainement le moyen le plus lisible s'il s'agit à la fois de variables locales ou de propriétés en lecture seule. Cela montre clairement le behvaior. Les membres vars seraient plus compliqués. L'idée de la fonction d'opérateur dans l'autre réponse est certes concise, mais masque la façon dont elle traite la nullité, donc je dirais que la lisibilité est discutable. J'irais jusqu'à dire que pour les propriétés var , vous devez créer des copies val locales, puis utiliser cette solution. Comportement verbeux, mais très clair.


@ Tenfour04 "L'idée de la fonction d'opérateur dans les réponses est certes concise, mais masque la façon dont elle traite la nullité, donc je dirais que la lisibilité est discutable." Pourriez-vous nous en dire davantage?


@DiegoMarin Je vous ai répondu en haut.


Eh bien, ne sont pas utilisés autant de fois, je ne les ai probablement jamais utilisés uwu.



0
votes

La réponse dépend vraiment de la sortie attendue de l'ajout de valeurs nulles.

Est-ce que 4 + null = null ou 4 + null = 4 ? et qu'en est-il de null + null ?

Dans mon cas, ce que je voulais, c'est:

  • 4 + 3 = 7
  • 4 + null = 4
  • null + null = null

La fonction ci-dessous réalise ce comportement

operator fun Int?.plus(other: Int?): Int? { 
    return if (this == null && other == null) {
        null
    } else {
        (a ?: 0) + (b ?: 0)
    }
}

...

val a: Int? = 1
val b: Int? = 1
val result = a + b

Vous pouvez également utiliser unesurcharge d'opérateur si vous voulez ce même comportement partout, mais lorsque vous l'utilisez, il n'est pas clair que son comportement est personnalisé.

private fun addNullable(a: Int?, b: Int?): Int? {
    return if (a == null && b == null) {
        null
    } else {
        (a ?: 0) + (b ?: 0)
    }
}

...

val a: Int? = 1
val b: Int? = 1
val result = addNullable(a, b)


0 commentaires