Skip to content

Instantly share code, notes, and snippets.

@aardouin
Created August 23, 2018 15:49
Show Gist options
  • Save aardouin/301eb88dcc2144a8090761e960ec9a13 to your computer and use it in GitHub Desktop.
Save aardouin/301eb88dcc2144a8090761e960ec9a13 to your computer and use it in GitHub Desktop.
if let else kotlin
//l'idée était de reproduire ce comportement de swift mais en kotlin
if let a = a {
//a is not null
}else{
//a is null
}
//la solution avec les Standard kotlin :
a?.also{ it ->
//a is not null
}?: run {
//a isNull
}
//je trouve ça pas très parlant, surtout à cause du run en fait
//Du coup j'ai fait deux mini fonctions et ça s'utilise comme ça et c'est réversible :
a.isNotNull { it ->
//a is not null and accessible as it
}.isNull {
//a is null
}
//Ca ne résoue pas les cas ou on veux récupérer une valeur a la sortie typiquement si on veux faire
val value = if(str != null) str else "undefined"
//Sur le nommage j'hésite avec plusieurs noms
isSet / isNull
ifSet / ifNull
ifNotNull / ifNull
notNull / otherwise
//J'aurais aimé ton ressenti d'expert kotlin là dessus, que ce soit sur le nommage ou l'implémentation
//Ou alors que je me fais chier parcequ'en fait ça existe déjà et je suis un tocard
//la définition :
inline fun <T> T?.isNotNull(block: (T) -> Unit):T? {
return this?.also(block)
}
inline fun <T> T?.isNull(block: () -> Unit): T? {
this?: block()
return this
}
@svinouze
Copy link

Je me dis que quitte à essayer de dupliquer ce comportement on aurait davantage intérêt à dupliquer le comportement de guard qui pour le coup vérifie que ta valeur est présente et la renvoit, sinon te fournit un block qui correspond pour le coup à ton else.

On aurait qqchose comme ça

inline fun <T> T.guard(block: T.() -> Unit): T {
    if (this == null) block()
    return this
}

Sinon tu as le takeIf ou juste le elvis operator qui peut être intéressant selon les situations

D'ailleurs j'ai trouvé la plupart de ces choses dans cet article qui je trouve explique plutôt bien la problématique.

@svinouze
Copy link

J'en ai parlé à la team iOS et il y a une nuance importante avec le guard que je propose car le guard sur iOS oblige au niveau du compilateur à return ou throw dans le block de complétion :)
Après ce guard que je propose est à mon sens une bonne alternative. Sinon le isNotNull/isNull que tu proposes marche aussi même si ça n'apporte pas énormément par rapport à un if/else hormis le scope sur ton objet. Mais si tu as vmt besoin du scope peut être que takeIf est une meilleure alternative ;)
Dis moi ce que tu en penses :)

@aardouin
Copy link
Author

aardouin commented Aug 24, 2018

Ouai en fait ton guard fait la meme chose que mon ifNull au final, tu as juste écrit if == null alors que j'ai utilisé le elvis.

Le but le mon ifNull / ifNotNull c'est surtout de pouvoir faire ce genre de choses

            ticket.validationDate.ifNotNull {
                validationDateTV.text = resources.getString(R.string.event_action_validation_date_detail_ticket,
                        it.toString(dateFormat),
                        it.toString(timeFormat))
            }.ifNull {
                validationDateTV.setText(R.string.event_action_validation_date_detail_ticket_no_date)
            }

Je pourrais aussi écrire, mais du du coup je suis pas scopé :

            validationDateTV.text = if(ticket.validationDate!= null){
                resources.getString(R.string.event_action_validation_date_detail_ticket,
                        ticket.validationDate?.toString(dateFormat),
                        ticket.validationDate?.toString(timeFormat))
            }else{
                resources.getString(R.string.event_action_validation_date_detail_ticket_no_date)
            }

Concernant le takeIf j'aime bien aussi , mais du coup c'est assez verbeux et ça me supprime pas l'optionnel.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment