Swift if let declaración en Kotlin

123

En Kotlin, ¿hay un equivalente al código Swift a continuación?

if let a = b.val {

}
else {

}
iori24
fuente

Respuestas:

255

Puede usar la letfunción -como esta:

val a = b?.let {
    // If b is not null.
} ?: run {
    // If b is null.
}

Tenga en cuenta que debe llamar a la runfunción solo si necesita un bloque de código. Puede eliminar el run-block si solo tiene un delineador después del elvis-operator ( ?:).

Tenga en cuenta que el runbloque se evaluará si bes nulo o si let-block se evalúa comonull .

Debido a esto, normalmente solo quieres una ifexpresión.

val a = if (b == null) {
    // ...
} else {
    // ...
}

En este caso, el else-block solo se evaluará si bno es nulo.

Marstran
fuente
41
No es equivalente. aNo se puede acceder al interior lety al runbloque.
Jacky Choi
6
aaún no está definido dentro del alcance de lety run. Pero puede acceder al valor de bdentro del letcon el parámetro implícitoit . Esto tiene el mismo propósito, supongo.
Marstran
1
El código rápido completa la asignación de aantes de esos bloques de código. Y ase puede acceder al interior.
Jacky Choi
1
¿A qué le asigna a? Si es así b, entonces ittiene exactamente el mismo propósito. ¿Se reasigna acon el resultado del val-bloque?
Marstran
3
Solo se puede acceder itdesde dentro del letbloque. El resultado del bloque leto runse asignará a a. El resultado es la última expresión del bloque. Utiliza la tarea después de que let / runha terminado, al igual que lo hace con cualquier otra tarea normal.
Marstran
51

Primero asegurémonos de entender la semántica del idioma Swift proporcionado:

if let a = <expr> {
     // then-block
}
else {
     // else-block
}

Significa esto: "si el <expr>resultado es un opcional no nulo, ingrese el then-bloque con el símbolo aligado al valor no envuelto. De lo contrario, ingrese al elsebloque.

Especialmente tenga en cuenta que a está limitado solo dentro del thenbloque . En Kotlin puede obtenerlo fácilmente llamando

<expr>?.also { a ->
    // then-block
}

y puede agregar un elsebloque como este:

<expr>?.also { a ->
    // then-block
} ?: run {
    // else-block
}

Esto da como resultado la misma semántica que el modismo Swift.

Marko Topolnik
fuente
11

Mi respuesta es totalmente una imitación de los demás. Sin embargo, no puedo entender su expresión fácilmente. Así que supongo que sería bueno dar una respuesta más comprensible.

En rápido:

if let a = b.val {
  //use "a" as unwrapped
}
else {

}

En Kotlin:

b.val?.let{a -> 
  //use "a" as unwrapped
} ?: run{
  //else case
}
Wu Yuan Chun
fuente
Usar en letlugar de alsosignifica que el runbloque se ejecutará siempre que el letbloque regrese null, que no es lo que queremos.
Marko Topolnik
6

A diferencia de Swift, no es necesario desenvolver el opcional antes de usarlo en Kotlin. Podríamos simplemente verificar si el valor no es nulo y el compilador rastrea la información sobre la verificación que realizó y permite usarla sin empaquetar.

En Swift:

if let a = b.val {
  //use "a" as unwrapped
} else {

}

En Kotlin:

if b.val != null {
  //use "b.val" as unwrapped
} else {

}

Consulte Documentación: (seguridad nula) para más casos de uso

Shahzin KS
fuente
Esto solo funciona si b es una variable local. ¿Qué pasa con las variables de clase?
Warpzit
5

if let declaración.

La Optional Binding(llamada if-letdeclaración) de Swift se usa para averiguar si un opcional contiene un valor y, de ser así, para hacer que ese valor esté disponible como una constante o variable temporal. Entonces, una Optional Bindingpara la if-letdeclaración es la siguiente:

if-letDeclaración de Swift :

let b: Int? = 50

if let a = b {
    print("Good news!")
} else {
    print("Equal to 'nil' or not set")
}

/*  RESULT: Good news!  */

En Kotlin, como en Swift, para evitar bloqueos causados ​​por intentar acceder a un valor nulo cuando no se espera, se proporciona una sintaxis específica (como b.let { }en el segundo ejemplo) para desenvolver correctamente nullable types:

Equivalente de Kotlin 1 de la if-letdeclaración de Swift :

val b: Int? = null
val a = b

if (a != null) { 
    println("Good news!")
} else { 
    println("Equal to 'null' or not set")
}

/*  RESULT: Equal to 'null' or not set  */

La letfunción de Kotlin , cuando se usa en combinación con el operador de llamada segura ?:, proporciona una forma concisa de manejar expresiones que aceptan valores NULL.

Equivalente de Kotlin 2 (función let en línea y operador de Elvis) de la if-letdeclaración de Swift :

val b: Int? = null

val a = b.let { nonNullable -> nonNullable } ?: "Equal to 'null' or not set"
println(a)

/*  RESULT: Equal to 'null' or not set  */

ingrese la descripción de la imagen aquí

guard let declaración.

guard-letdeclaración en Swift es simple y poderosa. Comprueba si hay alguna condición y si se evalúa como falsa, entonces se elseejecuta la declaración que normalmente saldrá de un método.

Exploremos la guard-letdeclaración de Swift :

let b: Int? = nil

func testIt() {
    guard let a = b else {
        print("Equal to 'nil' or not set")
        return
    }
    print("Good news!")
}
testIt()

/*  RESULT: Equal to 'nil' or not set  */

Efecto similar de Kotlin de la guard-letdeclaración de Swift :

A diferencia de Swift, en Kotlin, no hay ninguna declaración de guardia . Sin embargo, puede usar Elvis Operator- ?:para obtener un efecto similar.

val b: Int? = 50

fun testIt() {
    val a = b ?: return println("Equal to 'null' or not set")
    return println("Good news!")
}
testIt()

/*  RESULT: Good news!  */

Espero que esto ayude.

Andy Fedoroff
fuente
4

A continuación, se explica cómo ejecutar código solo cuando nameno es nulo:

var name: String? = null
name?.let { nameUnwrapp ->
    println(nameUnwrapp)  // not printed because name was null
}
name = "Alex"
name?.let { nameUnwrapp ->
    println(nameUnwrapp)  // printed "Alex"
}
Александр Яковенко
fuente
si nombre == código nulo en {} no se ejecuta, si el nombre es String - código de ejecución: nombreUnwrapp == nombre.
Александр Яковенко
1
No creo que esto sea lo que está preguntando OP, estoy seguro de que OP ya sabe lo que lethace, pero la pregunta es sobre la elseestrategia que se ejecuta si el objeto en el que letse llama es null. Swift lo tiene de una manera más natural (discutible). Pero después de haber hecho mucho a Kotlin y Swift, desearía que Kotlin tuviera un desenvolvimiento simple como lo hace Swift.
kalehv
2

Aquí está mi variante, limitada al caso muy común "si no nulo".

En primer lugar, defina esto en alguna parte:

inline fun <T> ifNotNull(obj: T?, block: (T) -> Unit) {
    if (obj != null) {
        block(obj)
    }
}

Probablemente debería serlo internal, para evitar conflictos.

Ahora, convierta este código Swift:

if let item = obj.item {
    doSomething(item)
}

A este código de Kotlin:

ifNotNull(obj.item) { item -> 
    doSomething(item)
}

Tenga en cuenta que, como siempre con los bloques en Kotlin, puede eliminar el argumento y usar it:

ifNotNull(obj.item) {
    doSomething(it)
}

Pero si el bloque tiene más de 1-2 líneas, probablemente sea mejor ser explícito.

Esto es tan similar a Swift como pude encontrar.

noamtm
fuente
0

Hay una forma similar en kotlin de lograr el estilo de Swift if-let

if (val a = b) {
    a.doFirst()
    a.doSecond()
}

También puede asignar varios valores que aceptan valores NULL

if (val name = nullableName, val age = nullableAge) {
    doSomething(name, age)
}

Este tipo de enfoque será más adecuado si los valores que aceptan valores NULL se utilizan más de una vez. En mi opinión, ayuda desde el aspecto del rendimiento porque el valor anulable se comprobará solo una vez.

fuente: Discusión de Kotlin

Ricardo
fuente
1
Tenga en cuenta que el enfoque que está mostrando no se compila actualmente. Es solo una sugerencia sobre cómo alterar el lenguaje Kotlin para abordar este problema. Por tanto, esta no es una solución válida.
Peter F
0

Estoy agregando esta respuesta para aclarar la respuesta aceptada porque es demasiado grande para un comentario.

El patrón general aquí es que puede usar cualquier combinación de las funciones de alcance disponibles en Kotlin separadas por el operador de Elvis de esta manera:

<nullable>?.<scope function> {
    // code if not null
} :? <scope function> {
    // code if null
}

Por ejemplo:

val gradedStudent = student?.apply {
    grade = newGrade
} :? with(newGrade) {
    Student().apply { grade = newGrade }
}
Sir Codesalot
fuente
-1

La opción más limpia en mi opinión es esta

Rápido:

if let a = b.val {

} else {

}

Kotlin

b.val.also { a ->

} ?: run {

}
Stiiv
fuente
-1

Swift if let declaración en Kotlin

La respuesta corta es usar IF-ELSE simple ya que en el momento de este comentario no hay equivalente en Kotlin LET,

    if(A.isNull()){
// A is null
    }else{
// A is not null
    }
bastami82
fuente