1

これがコンパイラエラーを生成する理由を理解しています:

let initialProducer = SignalProducer<Int, NoError>(value:42)
let sideEffectProducer = initialProducer.on(next: { (answer: Int) in
  return _
})

エラーは

タイプ '(Int) -> _' の値を予期される引数タイプ '(Int -> ())' に変換できませんか?

したがって、パラメーターは、返さnextれるパラメーターを使用してクロージャーを受け取ります。IntVoid_

しかし、なぜこれはうまくコンパイルされるのですか:

let initialProducer = SignalProducer<Int, NoError>(value:42)
let sideEffectProducer = initialProducer.on(next: { (answer: Int) in
  return ""
})

を返していますがStringVoidなぜコンパイラは文句を言わないのでしょうか?

4

1 に答える 1

1

_何もありませ。何にでもマッチするパターン、またはパターンの一部です。結果を気にしないことを示すために、割り当てステートメントで使用することもできます。

_ = foo()  // Ignore result returned from foo

クロージャーで、何も返さない場合は、次のいずれかを行います。

return

または、閉鎖の終わりにいる場合は、リターンを完全に省略します。

を返す_と、Swift はクロージャーの署名を理解できません。次のようにして、それを実証できます。

let bar = { return _ }  // Unable to infer closure return type in current context

を削除すると、 になるため、正常_にコンパイルされます。bar() -> ()

_Swift は、関数から戻ろうとした場合のように、より適切なエラー メッセージを表示できたはずです。

func foo() {
    return _  // '_' can only appear in a pattern or on the left side of an assignment
}

では、なぜ機能return ""するのでしょうか。ここに手がかりがあります。

単一行のクロージャーの周りには、明らかに奇妙な点がいくつかあります。あなたのものに似た次の例を考えてみましょう:

func doit(handler: (Int) -> ()) {
    handler(17)
    print("doit is done")
}

doit() { (answer: Int) in
    //print(answer + 1)
    return ""
}

これを実行すると、次の出力が生成されます。

やりました

したがって、あなたの例doitがクロージャを期待しているように、(Int) -> ()クロージャーを渡しています(Int) -> String。そして、それは動作します...

print(answer + 1)ただし、行のコメントを外すと、 return ""then はエラーになります。

void 関数での予期しない非 void 戻り

于 2016-05-14T15:39:31.633 に答える