追記
- Warningは正しかったです。
問題
- 以下はどういう出力になるでしょうか。
func foo() {
print(#function)
return // ← この後の処理は一旦無視したいからreturnしておこう
bar()
}
func bar() {
print(#function)
}
答え
-
bar()
も実行され出力されます。
foo()
bar()
理由
- 構文上、returnの後の改行は無視されて解釈されるので
return bar()
となり、bar()
が実行されるため。
func foo() { // 暗黙的に戻り値はVoidを返す関数
print(#function)
return
bar() // return bar() と解釈されるのでbar()は実行される
}
func bar() { // 暗黙的に戻り値はVoidを返す関数
print(#function)
}
- 以下が構文上許されているのと同じ意味です。
func baz() -> Int {
return
1
}
解決方法
- セミコロンをつけます。
func foo() { // 暗黙的に戻り値はVoidを返す関数
print(#function)
return; // セミコロンをつければ `return ()` として解釈される
bar() // 実行されない
}
バグ?
追記
- あれ!Warningの内容が Expression following 'return' is treated as an argument of the 'return' ('return' に続く式は'return'の引数として扱われます) だ!よく一時的な早期returnで遭遇する
Code after 'return' will never be executed
と勘違いしていた…なのでWarningはあっていますね。
-
あってる🙇♂️return
後の改行が無視されて解釈されるのは言語仕様としては正しいと思いますが、WarningでExpression following 'return' is treated as an argument of the 'return'
が表示されるのはバグだと思われます。
- ちなみにIntの方も表示された…。
まとめ
- Voidを返す関数でreturnを使う場合はセミコロンをつけないと意図しない挙動になる可能性がある。 追記: Warningはちゃんと読みましょう。。。
-
DevSapにて
return
が無視されるんだけどって話題が出て、僕自身も遭遇した経験があるので今回調査してみました。今までは差分コンパイル時のバグかな?って思ってreturn
は避けてコメントアウトするようにしていたのですが、今回やっと原因がわかりました。これは罠すぎる。。。