SwiftのStructの値渡し、write-back（≒ 参照渡し）、CoWの挙動確認

# 結論

- クロージャへは参照渡し、キャプチャリストを使えば値渡し
- 関数へは値渡し、inoutを使えば ~~参照渡し~~ write-back

## Copy-on-Write (CoW)

- SwiftのArrayやStringはパフォーマンスを考慮して、内部的にCoWが実装されている

# 確認

## 環境

- Xcode 9.4
- Swift 4.1

## Playground

```swift
import Foundation

func address(of object: UnsafeRawPointer) -> String {
    let addr = Int(bitPattern: object)
    return String(format: "%p", addr)
}

func printLine(_ line: Int = #line) {
    print("#L\(line)")
}

print("--- Clousure: Int ---\n")
do {
    var value = 10
    
    let closure1 = {
        print("- value = \(value) (\(address(of: &value)))") // valueは参照渡し
    }
    
    let closure2 = { [value] in
        print("- value = \(value) ← 値渡しなので影響を受けない") // valueは値渡し
    }
    
    let closure3 = {
        value += 10
        print("- value = \(value) (\(address(of: &value)))") // valueは参照渡し
    }
    
    printLine()
    print("- value = \(value) (\(address(of: &value)))") // value = 10
    
    printLine()
    closure1() // value = 10
    
    printLine()
    value = 20
    print("- value = \(value) (\(address(of: &value)))")
    closure1() // value = 20 (参照渡しなので反映されている)
    
    printLine()
    closure2() // value = 10 (値渡しなので反映されていない)
    
    printLine()
    closure3() // value = 30
    
    printLine()
    print("- value = \(value) (\(address(of: &value)))") // value = 30 (closure3での変更が反映されている)
}

print("\n--- Clousure: [Int] ---\n")
do {
    var values = [10]
    
    let closure1 = {
        print("- values = \(values) (\(address(of: &values)))") // valueは参照渡し
    }
    
    let closure2 = { [values] in
        print("- values = \(values) ← 値渡しなので影響を受けない") // valueは値渡し
    }
    
    let closure3 = {
        values.append(values.last! + 10) // CoW
        print("- values = \(values) (\(address(of: &values))) ← CoWによりバッファへのポインタが変更されていることが確認できる") // valueは参照渡し
    }
    
    printLine()
    print("- values = \(values) (\(address(of: &values)))")
    
    printLine()
    closure1() // values = [10]
    
    printLine()
    values.append(20) // CoW
    print("- values = \(values) (\(address(of: &values))) ← CoWによりバッファへのポインタが変更されていることが確認できる") // values = [10, 20]
    closure1() // values = [10, 20] (参照渡しなので反映されている)
    
    printLine()
    closure2() // values = [10] (値渡しなので反映されていない)
    
    printLine()
    closure3() // value = [10, 20, 30]
    
    printLine()
    print("- values = \(values) (\(address(of: &values)))") // value = [10, 20, 30] (closure3での変更が反映)
}

print("\n--- Function: Int ---\n")
do {
    var value = 10
    
    func function1(_ value: inout Int) {
        print("- value = \(value) (\(address(of: &value)))") // valueは参照渡し
    }
    
    func function2( _ value: Int) {
        print("- value = \(value) ← 値渡しなので影響を受けない")  // valueは値渡し
    }
    
    func function3(_ value: inout Int) {
        value += 10
        print("- value = \(value) (\(address(of: &value)))") // valueは参照渡し
    }
    
    printLine()
    print("- value = \(value) (\(address(of: &value)))") // value = 10
    
    printLine()
    function1(&value) // value = 10
    
    printLine()
    value = 20
    print("- value = \(value) (\(address(of: &value)))") // value = 20
    
    printLine()
    function3(&value) // value = 30
    
    printLine()
    print("- value = \(value) (\(address(of: &value)))") // value = 30 (function3での変更が反映されている)
}

print("\n--- Function: [Int] ---\n")
do {
    var values = [10]
    
    func function1(_ values: inout [Int]) {
        print("- values = \(values) (\(address(of: &values)))") // valuesは参照渡し
    }
    
    func function2( _ values: [Int]) {
        print("- values = \(values) ← 値渡しなので影響を受けない")  // valuesは値渡し
    }
    
    func function3(_ values: inout [Int]) {
        values.append(values.last! + 10) // CoW
        print("- values = \(values) (\(address(of: &values))) ← CoWによりバッファへのポインタが変更されていることが確認できる") // valuesは参照渡し
    }
    
    printLine()
    print("- values = \(values) (\(address(of: &values)))") // values = [10]
    
    printLine()
    function1(&values) // values = [10]
    
    printLine()
    values.append(20) // CoW
    print("- values = \(values) (\(address(of: &values))) ← CoWによりバッファへのポインタが変更されていることが確認できる") // values = [10, 20]
    
    printLine()
    function3(&values) // value = [10, 20, 30]
    
    printLine()
    print("- values = \(values) (\(address(of: &values)))") // values = [10, 20, 30] (function3での変更が反映)
}
```

## 結果

```
--- Clousure: Int ---

#L31
- value = 10 (0x608000021d90)
#L34
- value = 10 (0x608000021d90)
#L37
- value = 20 (0x608000021d90)
- value = 20 (0x608000021d90)
#L42
- value = 10 ← 値渡しなので影響を受けない
#L45
- value = 30 (0x608000021d90)
#L48
- value = 30 (0x608000021d90)

--- Clousure: [Int] ---

#L69
- values = [10] (0x600000054ed0)
#L72
- values = [10] (0x600000054ed0)
#L75
- values = [10, 20] (0x60c0000553b0) ← CoWによりバッファへのポインタが変更されていることが確認できる
- values = [10, 20] (0x60c0000553b0)
#L80
- values = [10] ← 値渡しなので影響を受けない
#L83
- values = [10, 20, 30] (0x60c00006aba0) ← CoWによりバッファへのポインタが変更されていることが確認できる
#L86
- values = [10, 20, 30] (0x60c00006aba0)

--- Function: Int ---

#L107
- value = 10 (0x7ffeeaabede8)
#L110
- value = 10 (0x7ffeeaabede8)
#L113
- value = 20 (0x7ffeeaabede8)
#L117
- value = 30 (0x7ffeeaabede8)
#L120
- value = 30 (0x7ffeeaabede8)

--- Function: [Int] ---

#L141
- values = [10] (0x60c000056160)
#L144
- values = [10] (0x60c000056160)
#L147
- values = [10, 20] (0x604000055410) ← CoWによりバッファへのポインタが変更されていることが確認できる
#L151
- values = [10, 20, 30] (0x604000066b60) ← CoWによりバッファへのポインタが変更されていることが確認できる
#L154
- values = [10, 20, 30] (0x604000066b60)
```

# 参考

- [Use Copy-On-Write With Swift Value Types](https://marcosantadev.com/copy-write-swift-value-types/)
- [SwiftのArrayが実はすばらしかった](https://qiita.com/koher/items/47f444200d4e02b6414e)
- [【Swift】closureでstructがキャプチャーされるときに参照になっていた](https://qiita.com/marty-suzuki/items/9ef45b2dba792a08faff)