ぼろぼろ平原

困った

Rubyの「if a = b」とSwiftの「if let a = b」は意味が異なる

SwiftRubyに似ていると言われることがある。(c.f. Swiftは○○に似ている)。 しかし、見た目は似ているけれど意味が異なる構文がある。 その一つに、代入を伴うif文がある。

Rubyif a = b

実行すると"false"が出力される。

b = false

if a = b
  puts("true")
else
  puts("false")
end

Swiftif let a = b

実行すると"true"が出力される。

let b:Bool?
b = false

if let a = b {
    println("true")
} else {
    println("false")
}

どうしてこうなった

Rubyのifの動作

Rubyif a = bは次の動作をする。

  1. 代入
  2. 分岐

それぞれを分けて書くとこうなる。

b = false

# 1. 代入
condition = (a = b) #=> false

# 2. 分岐
if condition
  puts("true")
else
  puts("false")
end

まず、a = bで代入が行われる。 この部分がfalseに評価され分岐条件になるので、"false"が出力される。

Swiftのif動作

一方、Swiftif let a = bは次の動作をする。

  1. Optionalの判別
  2. 分岐
  3. 代入

それぞれを分けて書くとこうなる。

let b:Bool?
b = false

// 1. Optionalの判別
let condition = (b != nil) // true

// 2. 分岐
if condition {
    // 3. 代入
    let a = b!
    println("true")
} else {
    println("false")
}

まず、b != nilでOptionalの判別が行われる。 分岐条件がtrueなので、let a = b!でforce unwrap&代入した後、"true"が出力される。

これは「optional binding」と呼ばれる機能で、Optional型の変数をunwrapする方法の一つ。