on Fri May 20 2016, Matthew Johnson <[email protected]> wrote:
>> 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). I am not making a strong argument against that, though it might be reasonable. I am mostly arguing in favor of a default definition of == for all reference types that is equivalent to ===. > 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 -- -Dave _______________________________________________ swift-evolution mailing list [email protected] https://lists.swift.org/mailman/listinfo/swift-evolution
