Swift,如果在Kotlin中让let语句


123

在Kotlin中,下面的Swift代码是否等效?

if let a = b.val {

}
else {

}

Answers:


255

您可以let像这样使用-function:

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

请注意,run仅在需要代码块时才需要调用该函数。run如果您仅在Elvis-operator(?:)之后只有一个衬垫,则可以删除-block 。

请注意,run如果b为null或let-block的结果为,则将对该块进行评估null

因此,您通常只需要一个if表达式。

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

在这种情况下,else-block仅在b不为null时被评估。


40
这不是等效的。a无法在内部访问letrun阻止。
杰基·崔

6
a没有的范围内定义还letrun。但是您可以使用隐式参数访问b内部的值。我猜这达到了相同的目的。letit
marstran

1
快速代码完成了a这些代码块之前的分配。并且a可以在里面访问。
Jacky Choi)

1
它分配给a什么?如果是b,则it可以达到完全相同的目的。它是否a使用val-block 的结果重新分配?
marstran

3
您只能itlet块内访问。letrun块的结果将分配给a。结果是块中的最后一个表达式。您可以 let / run完成使用作业,就像处理其他任何普通作业一样。
marstran

51

首先确保我们了解所提供的Swift习语的语义:

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

这意味着:“如果<expr>结果为非null可选,请输入then-block,并将符号a绑定到未包装的值。否则,请输入该else块。

特别要注意的是,a仅在then-block中绑定。在Kotlin中,您可以通过致电轻松获得

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

您可以添加else-block,如下所示:

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

这导致了与Swift惯用语相同的语义。


11

我的回答完全是别人的模仿。但是,我不容易理解它们的表达。因此,我想提供一个更容易理解的答案会很好。

迅速:

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

}

在Kotlin:

b.val?.let{a -> 
  //use "a" as unwrapped
} ?: run{
  //else case
}

使用let代替代替also意味着run只要let块返回null,块就会执行,这不是我们想要的。
Marko Topolnik,

6

与Swift不同,在Kotlin中使用它之前,不必解开可选选项。我们可以检查该值是否为非null,并且编译器跟踪有关您执行的检查的信息,并允许将其用作未包装的。

在Swift中:

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

}

在Kotlin:

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

}

有关更多此类用例,请参阅文档:(零安全)


仅当b是局部变量时才有效。那类变量呢?
Warpzit

5

if let 声明。

Swift的Optional Binding(所谓的if-let语句)用于找出可选变量是否包含值,如果是,则使该值可用作临时常量或变量。因此,Optional Bindingfor if-let语句如下:

斯威夫特的if-let声明:

let b: Int? = 50

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

/*  RESULT: Good news!  */

在Kotlin中,就像在Swift中一样,为了避免在不期望的情况下尝试访问null值而导致崩溃,提供了一种特定的语法(例如b.let { }第二个示例)来正确解包nullable types

Kotlin相当于 Swift if-let声明的1:

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  */

let当与安全调用运算符结合使用时,Kotlin 函数?:提供了一种简洁的方法来处理可为空的表达式。

Swift 声明的Kotlin等效项2 (内联let函数和Elvis运算符)if-let

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  */

在此处输入图片说明

guard let 声明。

guard-letSwift中的语句简单而强大。它检查某种条件,如果其评估结果为假,则else执行该语句,通常该语句将退出方法。

让我们探讨一下Swift的guard-let声明:

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  */

科特林对斯威夫特guard-let声明的类似影响

与Swift不同的是,在Kotlin中,根本没有后卫声明。但是,您可以使用Elvis Operator?:获得类似的效果。

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!  */

希望这可以帮助。


4

仅在name不为null 时执行代码的方法如下:

var name: String? = null
name?.let { nameUnwrapp ->
    println(nameUnwrapp)  // not printed because name was null
}
name = "Alex"
name?.let { nameUnwrapp ->
    println(nameUnwrapp)  // printed "Alex"
}

如果name == {}中的空代码不执行,如果name为String-代码execute:nameUnwrapp == name。
АлександрЯковенко

1
我不认为这是OP所要问的,我确定OP已经知道要做什么let,但是问题是关于被调用else的对象是时执行的策略。Swift以更自然(可争论)的方式提供了它。但是我已经做了很多Kotlin和Swift的工作,但我希望Kotlin能够像Swift一样进行简单的包装。letnull
kalehv

2

这是我的变体,限于非常常见的“如果不是null”情况。

首先,在某处定义它:

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

可能应该是internal,以避免冲突。

现在,转换此Swift代码:

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

对此Kotlin代码:

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

请注意,与Kotlin中的块一样,您可以删除参数并使用it

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

但是,如果块多于1-2行,则最好是明确的。

我发现这与Swift类似。


0

在Kotlin中,有一种类似的方法可以实现Swift的if-let样式

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

您还可以分配多个可为空的值

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

如果可为空的值使用了1次以上,则这种方法将更适合。我认为,这从性能方面来说是有帮助的,因为可空值将仅被检查一次。

来源:Kotlin讨论


1
请注意,您显示的方法当前无法编译。这仅是关于如何更改Kotlin语言以解决此问题的建议。因此,这不是有效的解决方案。
彼得F

0

我要添加此答案以澄清接受的答案,因为它太大了,无法发表评论。

这里的一般模式是,您可以使用由Elvis运算符分隔的Kotlin中可用的示波器功能的任意组合,如下所示:

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

例如:

val gradedStudent = student?.apply {
    grade = newGrade
} :? with(newGrade) {
    Student().apply { grade = newGrade }
}

-1

我认为最干净的选择是

迅速:

if let a = b.val {

} else {

}

科特林

b.val.also { a ->

} ?: run {

}

-1

Swift,如果在Kotlin中让let语句

简短的答案是使用简单的IF-ELSE,因为在发表此评论时,Kotlin LET中没有等效的功能,

    if(A.isNull()){
// A is null
    }else{
// A is not null
    }
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.