> On May 20, 2016, at 7:40 PM, Brent Royal-Gordon via swift-evolution 
> <[email protected]> wrote:
> 
>> The Any-class requirement could replace the current `AnyObject` protocol 
>> with a typealias like this: `typealias AnyObject = Any<class>`
>> 
>> Assume Swift would introduce Any-struct and Any-enum requirement one day. 
>> How would one name a typealias for these, where `AnyClass` means 
>> `AnyObject.Type`?
>> 
>> I suggest we drop the current `AnyClass` and rename `AnyObject` to 
>> `AnyClass`. If one would need the old `AnyClass` behavior it will become 
>> `AnyClass.Type`.
> 
> I propose that we deprecate `AnyObject` in favor of `Any<class>`. No 
> typealias, just directly using `Any<>`. We would also deprecate `AnyClass` in 
> favor of `Any<class>.Type`. (Presumably we would do this by providing 
> `AnyObject` and `AnyClass` typealiases in Swift 3, but marking them as 
> deprecated.)
> 
> I like this approach because it exposes people to `Any<>` and more quickly 
> gets them to see how it's connected to a protocol declaration's conformance 
> list. They might then guess that `Any<>` has other capabilities from that 
> list, like the ability to handle multiple protocols.
> 
>> In the future we could have typealiases like this, which are more clear:
>> 
>> `typealias AnyClass = Any<class>`
>> `typealias AnyStruct = Any<struct>`
>> `typealias AnyEnum = Any<enum>`
> 
> Even in the long term, I don't see any good reason to support `Any<struct>` 
> vs. `Any<enum>`. There is no semantic distinction* between a struct and an 
> enum; you can always implement something enum-y using a struct with a mode 
> field, or something struct-y using an enum with associated values. `Bool`, 
> for instance, was once an enum and was changed to a struct for implementation 
> reasons; this change made no difference to how it was used.
> 
> Now, there *is* a semantic distinction between struct/enum and class—one is a 
> value type, the other is a reference type. To support that distinction, it 
> might make sense to support an `Any<value>` or `Any<!class>` syntax. Again, I 
> would prefer to use the raw `Any<>` syntax, though, not a typealias.

You can implement reference types with value semantics and value types with 
reference semantics.  Until the compiler can verify value semantics I am not 
sure there is a benefit to `any<value>`.  The semantic distinction is what is 
important.  There has been discussion about strengthening the “value type == 
value semantics” and “reference type == reference semantics” relations but that 
hasn’t yet moved beyond talk.

> 
> (I've read the arguments about pure vs. non-pure value type conformances and 
> I'm not convinced. It is always possible to nominally "conform" to a protocol 
> in a way that actually undermines its guarantees; for example, you could 
> implement `RangeReplaceableCollection.remove(at:)` as a no-op. The compiler 
> cannot reject all invalid conformances; it can only reject ones which it can 
> trivially show are invalid, because for instance they do not even attempt to 
> provide a required method. Similarly, the compiler may not be able to prove 
> you are providing value semantics, but it *can* reject conformances of 
> reference types to a protocol requiring value semantics, since those cannot 
> possibly be valid conformances.

Immutable reference types actually *can* provide valid value semantics (at 
least as long as as they can provide their own implementation of `==` which I 
believe Dave A is arguing against).

There is a big difference between semantics that the compiler *could* but *does 
not yet* verify and semantics that simply cannot be verified.

> 
> Incidentally, I am not convinced that it *ever* makes sense to have a 
> mutating protocol which does not specify either value or reference semantics.
> The only intentional Stdlib examples I'm aware of are `IteratorProtocol` and 
> `OutputStream`, and I think both of those should be reference-only.
> 
> (On the other hand, it might make sense to be able to mark a struct or enum 
> as "this is actually a reference type". For instance, if you import libc, 
> UnsafeMutablePointer<FILE> is essentially a reference type. But on the 
> gripping hand, you *could*, and perhaps should, just wrap it in a class, 
> either through importer magic or a manually-created type. That would permit 
> you to conform it to reference-typed mutating protocols.))

This is a good example of why the semantics aren’t so simple.  

> 
> 
> 
> * There *are* some distinctions, particularly in pattern matching, but 
> protocols can't model them anyway. Incidentally, it is not possible to 
> satisfy static property/method requirements with cases, but it probably 
> should be:
> 
>    protocol OptionalProtocol { 
>        associatedtype W
>        static var none: Self { get } 
>        static func some(value: W) -> Self 
>    } 
>    extension Optional: OptionalProtocol {
>        typealias W = Wrapped
>    }

I think there was discussion at some point about introducing enum case 
requirements into protocols.  But that is mostly tangential to this discussion.

> 
> 
> -- 
> Brent Royal-Gordon
> Architechies
> 
> _______________________________________________
> swift-evolution mailing list
> [email protected]
> https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to