J'essaie d'utiliser when expression dans Kotlin pour effectuer conditionnellement différentes logique étant donné différents cas pour une valeur. Certains des cas sont simples, par exemple. "quand la valeur est nulle", "quand la valeur est égale à X", mais j'ai au moins un cas qui est plus impliqué, où je dois appeler une autre fonction pour me dire si elle correspond ou non, par exemple. "lorsque la valeur correspond à mon prédicat".

Un exemple simplifié tiré de mon cas spécifique, l'objet considéré est de type Instant, et j'ai différents cas pour le gérer par rapport à Instant.now(). En réalité, c'est un champ imbriqué dont je compare l'horodatage dans certains cas, et d'autres champs dans d'autres cas.

val timestamp: Instant? = myOtherFunctionThatReturnsAnInstant()
val result = when (timestamp) {
  null -> "result when timestamp is null"
  isInThePast(timestamp) -> "result when timestamp in the past ${timestamp.epochSecond()}" // <- question regarding the condition on this line
  else -> "result when timestamp is in the future ${timestamp.epochSecond()}"
}

Je peux obtenir cela pour compiler une fonction définie appelée isInThePast(timestamp: Instant?): Instant. Mais comme le type de retour souhaité est Instant et non Boolean, je ne comprends pas comment j'ai besoin d'implémenter cette fonction pour capturer des valeurs spécifiques dans la condition (c'est-à-dire timestamp.isBefore(Instant.now())).

Je suis plus expérimenté avec java, je pense à une fonctionnalité Predicate<Instant>, mais je ne sais pas comment (ou si?) Peut s'intégrer avec le conditionnel Kotlin when. Des manières plus verbeuses me viennent à l'esprit, mais ma question est de savoir si when prend en charge ce type de condition, et si oui, comment implémenter l'expression pour le faire?

modifier , pour ajouter des recherches antérieures:

N'ayant trouvé que des exemples basiques d'utilisation de when, y compris les conditions is X et in X, voici un extrait de https://superkotlin.com/kotlin-when-statement/ qui me porte à croire que c'est possible, mais ne développe pas ou ne fournit pas le code pertinent pour moi pour voir.

var result = when(number) {
    0 -> "Invalid number"
    // OK: check returns an Int
    check(number) -> "Valid number"
    // OK: check returns an Int, even though it accepts a String argument
    checkString(text) -> "Valid number"
    // ERROR: not valid
    false -> "Invalid condition"
    else -> "Number too high"
}

Dans l'exemple ci-dessus, à quoi pourraient ressembler check(number) et checkString(text)?

0
wutch 10 mars 2021 à 03:05

2 réponses

Meilleure réponse

Une instruction when a un argument (entre parenthèses avant les accolades) ou non.

Lorsque vous fournissez un argument, vous êtes limité aux vérifications equals / is / in plutôt qu'aux expressions booléennes arbitraires. Ce que tous ces éléments ont en commun, c'est d'utiliser implicitement l'argument pour donner une valeur booléenne résultante.

Lorsque vous ne fournissez pas d'argument, vous pouvez utiliser des expressions arbitraires qui s'évaluent en booléens. Donc, si vous voulez des expressions arbitraires, vous ne pouvez pas avoir d'argument, et vous devez donc épeler votre égal / est / dans les comparaisons, par exemple:

val result = when {
  timestamp == null -> TODO()
  isInThePast(timestamp) -> TODO()
  else -> TODO()
}

Edit: Juste un hack amusant auquel j'ai pensé, pas vraiment sérieux, mais vous pouvez créer un objet que vous pouvez utiliser pour une vérification in afin que vous puissiez toujours utiliser l'instruction when avec un argument comme celui-ci:

object ThePast {
    operator fun contains(instant: Instant) = instant.isBefore(Instant.now())
}

// ...

when (timestamp) {
    null -> TODO()
    in ThePast -> TODO()
    else -> TODO()
}
2
Tenfour04 10 mars 2021 à 22:28

Je ne sais pas si j'ai compris votre question mais c'est ce que je comprends

val timestamp: Instant? = myOtherFunctionThatReturnsAnInstant()
fun isInThePast(value : Instant) : String{
    return when {
        value.isBefore(Instant.now()) -> "result when timestamp in the past ${value.epochSecond}"
        else -> "result when timestamp is in the future ${value.epochSecond()}"
    }
}
val result : String  = when (timestamp) {
    null -> "timestamp is null"
    else -> { isInThePast(timestamp) }
}

OU

val timestamp: Instant? = myOtherFunctionThatReturnsAnInstant()

val result : String  = when (timestamp) {
    null -> "timestamp is null"
    else -> {
        when {
            timestamp.isBefore(Instant.now()) -> "result when timestamp in the past ${timestamp.epochSecond}"
            else -> "result when timestamp is in the future ${timestamp.epochSecond()}"
        }
    }
}
1
TouchVàmadute Meelugsana 10 mars 2021 à 07:19