"AnyValue", "protocol MyProtocol : value" as counterpart to "AnyObject", ": class"


(Karl) #1

I was building a collection object recently, which stores an array of tuples: (Range<I>, T) - some generic type, and a range.
Part of the workings of the collection involves splitting these tuples, which means we need to split the Range (easy enough) and duplicate T.

In practice, I was using value types for T (it was another Array), so I could duplicate by assignment; but what if somebody stuck an NSArray or other reference-type in instead?

My first thought was - I could allow it, create some “Copyable” protocol and require conformance. But there are other guarantees I get from value types as well. Let’s say I had a sorted Array of T; if T could be a reference-type, anybody who gets a T from the collection could mutate it and invalidate the sort order at any time! That could lead to unexpected behaviour, such as infinite loops in binary-search algorithms, and it might not be obvious to a user of the collection how that happened (or that it’s even their fault - how are they supposed to know this is kept in a sorted Array, especially if it’s wrapped by another type, and that this particular search algorithm could infinitely loop if the Array is not sorted?). I could return a copy from the getter, but at this point I’m basically re-inventing value-type semantics for classes while creating burdensome requirements for actual value-types.

Actually, this is a problem with the language in general. While we have a way to specify that a generic type or protocol must obey reference-type semantics (via “<T where T:AnyObject>”, “protocol MyProtocol : class”), we don’t have a value-type semantic counterpart.

So I’d like to see us provide an “AnyValue” and “value” equivalent. We should be able to require that generic types or protocols are satisfied by values so we know how to treat them.


(Adrian Zubarev) #2

Might have a look at this thread, where value semantics is been discussed already: https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160502/016286.html (Should we rename "class" when referring to protocol conformance?)

I’m also proposing for a `Type` merging mechanism with the potential to replace `protocol<>` called `type<>` aka. `all<>` aka. `All<>` (and in some point the core team names a portion of it `Any<>` in their docs: https://github.com/apple/swift/blob/master/docs/GenericsManifesto.md).

My proposal thread is here: https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160502/016523.html ([Pitch] merge types and protocols back together with type<Type, Protocol, …>)

If you want to read my detailed design, take a look at this WIP draft: https://github.com/DevAndArtist/swift-evolution/blob/master/proposals/nnnn-merging-types-with-protocols.md
I will rewrite a few things when I find some time to match a few things from the GenericsManifesto.

Anyways may I sum a few of my thoughts up for you:

- from the GenericsManifesto we “might“ see something like “Generalized `class` constraints“ in Swifts future: `typealias AnyObject = protocol<class>`

- if my proposal will be accepted and `class` is generalized already we’ll have something like this: `typealias AnyObject = All<class>`
* `All<>` will create a type from all constraints inside the angle brackets, this will create a new `Type` like `All<UIView, SomeProtocol>` where `SomeProtocol` sits on the .dynamicType rather than on `UIView`
* this will solve this problem https://openradar.appspot.com/20990743
* future flattened version of `All<>` might have operators and could be expressed like this: `func foo(value: UIView & SomeProtocol)`

- there are two future directions in my proposal:
(1) `Any<>` which takes only one type from the angle brackets: `Any<String, Int>` or `String | Int`
(2) if we already have a generalized `class` keyword, so why we don’t get `struct` and `enum` as well?

With this we can create a typealias for `AnyValue` like this (at least for generalized extendable types):
`typealias AnyStruct = All<struct>`
`typealias AnyEnum = All<enum>`
`typealias AnyValue = Any<All<struct>, All<enum>>`
`typealias AnyValue = AnyStruct | AnyEnum`

The future might also see: `typealias AnyValue = Any<All<struct>, All<enum>, All<tuple>>`

But again I have to rewrite a lot of things in my proposal towards this direction. :wink:

···

--
Adrian Zubarev
Sent with Airmail

Am 15. Mai 2016 bei 05:20:29, Karl via swift-evolution (swift-evolution@swift.org) schrieb:

I was building a collection object recently, which stores an array of tuples: (Range<I>, T) - some generic type, and a range.
Part of the workings of the collection involves splitting these tuples, which means we need to split the Range (easy enough) and duplicate T.

In practice, I was using value types for T (it was another Array), so I could duplicate by assignment; but what if somebody stuck an NSArray or other reference-type in instead?

My first thought was - I could allow it, create some “Copyable” protocol and require conformance. But there are other guarantees I get from value types as well. Let’s say I had a sorted Array of T; if T could be a reference-type, anybody who gets a T from the collection could mutate it and invalidate the sort order at any time! That could lead to unexpected behaviour, such as infinite loops in binary-search algorithms, and it might not be obvious to a user of the collection how that happened (or that it’s even their fault - how are they supposed to know this is kept in a sorted Array, especially if it’s wrapped by another type, and that this particular search algorithm could infinitely loop if the Array is not sorted?). I could return a copy from the getter, but at this point I’m basically re-inventing value-type semantics for classes while creating burdensome requirements for actual value-types.

Actually, this is a problem with the language in general. While we have a way to specify that a generic type or protocol must obey reference-type semantics (via “<T where T:AnyObject>”, “protocol MyProtocol : class”), we don’t have a value-type semantic counterpart.

So I’d like to see us provide an “AnyValue” and “value” equivalent. We should be able to require that generic types or protocols are satisfied by values so we know how to treat them.
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution