Kotlinでのlet letステートメントの迅速化


123

Kotlinには、以下のSwiftコードに相当するものがありますか?

if let a = b.val {

}
else {

}

回答:


255

次のletように-function を使用できます。

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

runコードのブロックが必要な場合にのみ、関数を呼び出す必要があることに注意してください。runelvis-operator(?:)の後にonelinerしかない場合は、-blockを削除できます。

あることに注意してくださいrun場合、ブロックはいずれかで評価されますbnullである場合、またはlet-ブロック評価さへnull

このため、通常はif式だけが必要です。

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

この場合、else-blockは、bがnullでない場合にのみ評価されます。


41
それは同等ではありません。a内部にアクセスしletrunブロックすることはできません。
Jacky Choi

6
aletおよびのスコープ内ではまだ定義されていませんrun。ただし、暗黙的なパラメータを使用して、b内部の値にアクセスできletますit。これは私が推測するのと同じ目的を果たします。
marstran 2017年

1
Swiftコードは、aこれらのコードブロックの前にの割り当てを完了します。そして、a内部にアクセスすることができます。
Jacky Choi

1
それは何に割り当てられaますか?それはだ場合b、その後、itまったく同じ目的を果たします。-block aの結果で再割り当てされvalますか?
marstran 2017年

3
ブロックit内からのみアクセスできますletletor runブロックの結果はに割り当てられaます。結果は、ブロックの最後の式です。他の通常の割り当てと同じように、/の終了 に割り当てを使用します。letrun
marstran 2017年

51

まず、提供されたSwiftイディオムのセマンティクスを確実に理解してみましょう。

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

これは、「<expr>結果が非nilオプションになる場合は、thenラップaされていない値にバインドされたシンボルを使用して-blockを入力します。それ以外の場合は、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 {

}

コトリンでは:

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 {

}

コトリンでは:

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

}

ドキュメントを参照:(null-safety)そのような使用例


これは、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 { }、適切にアンラップするために特定の構文(2番目の例のような)が提供されていますnullable types

Swiftのif-let声明のKotlin相当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  */

Kotlinのlet関数をsafe-call演算子と組み合わせて使用​​すると、?:null許容式を簡単に処理できます。

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のステートメントはシンプルで強力です。それはいくつかの条件をチェックし、それがfalseと評価された場合、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  */

KotlinによるSwiftの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"
}

if name == nullコード({}の場合)、nameがStringの場合は実行されません-コード実行:nameUnwrapp == name。
АлександрЯковенко

1
これはOPが求めていることではないと思いますが、OPはすでに何をletしているのかわかっていると思いますが、問題は、呼び出さelseれたオブジェクトがの場合に実行される戦略についてletですnull。Swiftには、より自然な(議論の余地がある)方法があります。しかし、KotlinとSwiftの両方を何度も実行したので、SwiftのようにKotlinが簡単にアンラップできることを願っています。
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

Swiftのスタイルのif-letを達成するためにkotlinにも同様の方法があります

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

複数のnull許容値を割り当てることもできます

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

この種類のアプローチは、null許容値が1回以上使用される場合により適しています。私の意見では、null許容値は1回だけチェックされるため、パフォーマンスの面で役立ちます。

出典:Kotlinディスカッション


1
現在表示しているアプローチはコンパイルできないことに注意してください。これは、この問題に対処するためにKotlin言語を変更する方法に関する提案にすぎません。したがって、これは有効なソリューションではありません。
Peter F

0

コメントには大きすぎるため、受け入れられた回答を明確にするためにこの回答を追加します。

ここでの一般的なパターンは、次のようにエルビス演算子で区切られた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

Kotlinでのlet letステートメントの迅速化

簡単な答えは、このコメントの時点ではKotlin LETには同等のものがないため、単純なIF-ELSEを使用することです。

    if(A.isNull()){
// A is null
    }else{
// A is not null
    }
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.