[swift-evolution] Generic Subscripts

Brent Royal-Gordon brent at architechies.com
Fri Jan 13 20:33:57 CST 2017


> On Jan 13, 2017, at 9:50 AM, John McCall via swift-evolution <swift-evolution at swift.org> wrote:
> 
> I'm also not sure we'd ever want the element type to be inferred from context like this.  Generic subscripts as I see it are about being generic over *indexes*, not somehow about presenting a polymorphic value.

I think I have a pretty good use case for generic element types: you may want an index to carry the type of its element. For example, suppose you want to have a sort of dictionary whose keys are unique instances of a key class, and whose value type depends on the key instance:

	struct TypedDictionary {
		final class Key<T>: Hashable {
			init(of type: T.Type) {}
			
			var hashValue: Int { return ObjectIdentifier(self).hashValue }
			static func == (lhs: Key, rhs: Key) { return lhs === rhs }
		}
		
		private var storage: [AnyHashable: Any] = [:]
		
		subscript<T>(key: Key<T>) -> T? {
			get {
				return storage[key] as! T?
			}
			set {
				storage[key] = newValue as Any?
			}
		}
	}
	
	let messageKey = TypedDictionary.Key(of: String.self)
	let answerKey = TypedDictionary.Key(of: Int.self)
	
	var myDict = TypedDictionary()
	myDict[messageKey] = "Hello, world!"
	myDict[answerKey] = 42

I've wanted to do things like this in at least three or four different contexts; you could even imagine reflection being implemented this way, with typed `PropertyKey`s and a subscript available on all instances. You can work around it with methods, but it always feels unnatural, with vacuous method names like `value(for:)`.

I do agree that it is probably useless and certainly a little dangerous to have a generic parameter that's completely inferred from the return value, but you could make the same argument for methods, and yet we allow them there.

-- 
Brent Royal-Gordon
Architechies



More information about the swift-evolution mailing list