if let _ = hoge VS if hoge != nil について考える
はじめに
どうもこんにちは、TOSHです。普段はQiitaに記事を投稿することが多いのですが、せっかくなので、Zennでも記事を書いてみようと思い、初投稿記事になります。どっちのプラットフォームの方が書きやすいのか、閲覧数が多いのか気になるところですね。
よかったら、Qiitaの記事にも目を通してみてください。tosh_3
Swiftのnilチェック
Swiftのnilについてはまた別の機会に紹介しようと思うのですが、nilチェックを行う際に、よく見るコード大きく分けて、2通りなのではないでしょうか?
if let _ = hoge形式
if let _ = hoge {
// Do something
}
if hoge != nil形式
if hoge != nil {
// Do something
}
結果としてやっていることは、hogeという変数がnilかどうかをチェックして、nilでない場合には、動作を実行するというように、同じ挙動をしていると思うのですが、これらは実際にはどのような違いがあるのでしょうか?
実行レベルのチェック
ここについてどうと判断するのは難しいのですが、例えば、上記の動作を実行するファイルをそれぞれ使用して、
swiftc -O -emit-assembly Hoge.swift
のような形式で実行すると、どちらの形式も同じアセンブリが排出されます。
Lloh1: Lloh1:
add x8, x8, _$s4main4hogeSiSgvp@PAGEOFF add x8, x8, _$s4main4hogeSiSgvp@PAGEOFF
mov w9, #12 mov w9, #12
str x9, [x8] str x9, [x8]
strb wzr, [x8, #8] strb wzr, [x8, #8]
mov w0, #0 mov w0, #0
ret ret
一方で、Xcode上で、viewDidLoadの中に入れてあげ、breakpointを打ち、always show Assembly
で比較してみると、実行結果は異なります。
if let _ = hoge
-> 0x1004cbe54 <+36>: add sp, sp, #0x20 ; =0x20
0x1004cbe58 <+40>: ret
if hoge != nil
-> 0x102cffe20 <+36>: str xzr, [sp, #0x8]
0x102cffe24 <+40>: and w8, w8, w8
0x102cffe28 <+44>: strb w8, [sp, #0x10]
0x102cffe2c <+48>: ldrb w8, [sp, #0x10]
0x102cffe30 <+52>: tbnz w8, #0x0, 0x102cffe40 ; <+68> at ViewController.swift
0x102cffe34 <+56>: mov w8, #0x1
0x102cffe38 <+60>: str w8, [sp, #0x4]
0x102cffe3c <+64>: b 0x102cffe48 ; <+76> at ViewController.swift
0x102cffe40 <+68>: mov w8, #0x0
0x102cffe44 <+72>: str w8, [sp, #0x4]
0x102cffe48 <+76>: ldr w8, [sp, #0x4]
0x102cffe4c <+80>: tbz w8, #0x0, 0x102cffe54 ; <+88> at ViewController.swift:18:5
0x102cffe50 <+84>: b 0x102cffe54 ; <+88> at ViewController.swift:18:5
0x102cffe54 <+88>: add sp, sp, #0x30 ; =0x30
0x102cffe58 <+92>: ret
どうもif hoge != nil
形式の方が幾分か手数が多いように見えます。
とはいえ、この程度の命令の差で誤差の範囲に含まれると思われます。知らんけど。
なので、実行レベルではほぼ一緒であると考えて良いのではないでしょうか?
ではどちらを使用するべきなのか?
これについて良し悪しはあると思いますが、個人的には、if hoge != nil
形式を推します。
というのも、パフォーマンスに差分がないとすれば、可読性が決め手になってくるのではないでしょうか?
if let _ = hoge
というのは、wildcardである_
を使用しており、ぱっと見何をしているのかがみやすいのかというととてもわかりやすいとは言えません。if hoge != nil
の方が幾分かシンプルに見えやすいのではないでしょうか?
if let _ = hoge
の方が玄人感がしてかっこいいのですが、読んだ際の思考の手筈は、
1. hogeがnilかどうかチェックしている
2. hogeがnon nilの場合の値を定義
3. 定義した値は使用する予定がないので、wildcardにしておく
と三手になるのに対し、if hoge != nil
では、
1. hogeがnilかどうかチェックしている
と一手で表現できるので、こちらの方がシンプルな気がしますよね。という観点から個人的にはif hoge != nil
を推しています。
if let _ = hogeの方が好ましいケース
もし仮に既存のコードの中でif let _ = hoge
が多用されているのであれば、多用されている方を使用するべきだと思います。
あとは、今はwildcardでセットしているが将来的に、その値を使用する可能性があるのではあれば保守性の観点からif let _ = hoge
を使用するべきだと思います。
個人的には、
if let _ = hoge as? String {
// Do something
}
みたいなケースでも、if let _ = hoge
を使用する気がします。その方が綺麗に書けるので。
最後に
まあ、なので好みと言えば好みだと思います。
参考
Discussion