[swift-evolution] Proposals: (1) Forbidding custom `==` for value types, (2) `dispatch` keyword, (3) `default`-result for methods with `Self`, and (4) Poor-Mans-Existentials

Johannes Neubauer neubauer at kingsware.de
Wed Jul 20 08:13:18 CDT 2016


Dear Susan,

> Am 20.07.2016 um 14:14 schrieb Susan Cheng <susan.doggie at gmail.com>:
> 
> I forgot to reply, a shared value type can capture by multiple closures.
> 
> func twoThreads() -> (Thread, Thread) {
>     var shared_int = 0
>     return (Thread { shared_int = 1 }, Thread { shared_int = 2 })
> }

You are not sharing the value type, but the reference to it (so you share the surrounding function context *by reference* or more precisely via *call by sharing*). I use an array as example (and synchronous dispatch queues, to get a reliable answer), because its value is less „atomic“: 

```swift
var shared_array = [Int]()
var not_shared_array = shared_array
dispatch_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
    var not_shared_array = shared_array
    not_shared_array.append(1)
    print("not shared 1: \(not_shared_array)")
    shared_array.append(2)
    print("shared 2: \(shared_array)")
}

dispatch_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
    var not_shared_array = shared_array
    not_shared_array.append(3)
    print("not shared 3: \(not_shared_array)")
    shared_array.append(4)
    print("shared 4: \(shared_array)")
}

not_shared_array.append(5)
shared_array.append(6)
print("not shared: \(not_shared_array)")
print("shared: \(shared_array)“)

// prints:
// not shared 1: [1]
// shared 2: [2]
// not shared 3: [2, 3]
// shared 4: [2, 4]
// not shared: [5]
// shared: [2, 4, 6]
```

You could do this without closures using a reference type as a wrapper, but you still do not share the value instance but the wrapper:

```swift
class Wrapper {
    var shared_array = [Int]()
}

func appendNumber(w: Wrapper, n: Int) {
    w.shared_array.append(n)
}

func appendNumber(var v: [Int], n: Int) {
    v.append(n)
}

let wi = Wrapper(),
    vi = [Int]()

appendNumber(wi, n: 1)
appendNumber(vi, n: 2)
print(wi.shared_array)
print(vi)

// prints:
// [1]
// []
```

All the best
Johannes

> 
> Johannes Neubauer <neubauer at kingsware.de> 於 2016年7月18日星期一 寫道:
> 
> > Am 18.07.2016 um 06:47 schrieb Susan Cheng <susan.doggie at gmail.com>:
> >
> > so, you want to propose default == operator but not forbidding all peoples to custom == operator?
> > Why don't just adding the following function to std library?
> >
> > public func == <T : Equatable>(lhs: T, rhs: T) -> Bool {
> >     var lhs = lhs
> >     var rhs = rhs
> >     return memcmp(&lhs, &rhs, sizeof(T.self)) == 0
> > }
> 
> This does not work, because method parameters are statically dispatched. This function will never be executed for any type, that has a custom equality implementation. So this would not enforce this check upfront. You would need to copy this code to every custom implementation (which can be forgotten). Or you have to implement it like this
> 
> ```swift
> public func isSame(lhs: Any, rhs: Any) -> Bool {
>   // like above in your code
> }
> 
> public func ==(lhs: MyType, rhs: MyType) -> Bool {
>   if isSame(lhs, rhs: rhs) {
>     return true
>   }
>   // do custom behavior
> }
> ```
> 
> > Thread safety can't fixed by std library. Value type only can atomic compared when additional mutex provided.
> 
> Value types are either on the stack or they are **copied** to the heap (for protocol types with large value types). So, you don’t have any thread safety issues (as they are copied before they are changed in the new thread) as long as you don’t do (or check) anything on a property of a reference type, because the latter has shared **state**.



More information about the swift-evolution mailing list