Could this be addressed by allowing generic constraints on subscripts?
For example, with methods we can currently do:

struct Foo {
        var values:[Any] = []

        func get<T>(at:Int) -> T? {
                return values.indices.contains(at) ? values[at] as? T : nil
        }

        func get<T>(at:Int, as theType:T.Type) -> T? {
                return values.indices.contains(at) ? values[at] as? T : nil
        }

        mutating func set<T>(at:Int, to:T) {
                if values.indices.contains(at) { values[at] = to }
        }
}

let foo = Foo(values: [1.5, 2.5, 3.5, 1, 2, 3])
let a = foo.get(at: 0, as: Double.self)
let b:Double = foo.get(at: 1)!
let c:Int? = foo.get(at: 2)
let d = foo.get(at: 3, as: Double.self)
let e:Int = foo.get(at: 4)!
let f = foo.get(at: 5, as: Int.self)
i.e- the type is inferred from the call-site either with an explicit variable 
type, or by passing in the expected type as the second argument, which I think 
is a pretty neat way to do it.

If we could do the same with subscripts we could do something like:

struct Foo {
        var values:[Any] = []

        subscript<T>(_ at:Int) -> T? {
                get { return values.indices.contains(at) ? values[at] as? T : 
nil }
                set { if values.indices.contains(at) { values[at] = newValue } }
        }

        subscript<T>(_ at:Int, as theType:T.Type) -> T? {
                return values.indices.contains(at) ? values[at] as? T : nil
        }
}

let foo = Foo(values: [1.5, 2.5, 3.5, 1, 2, 3])
let a = foo[0, as: Double.self]
let b:Double = foo[1]!
let c:Int? = foo[2]
let d = foo[3, as: Double.self]
let e:Int = foo[4]!
let f = foo[5, as: Int.self]

Are generic constraints on subscripts part of the generics manifesto?

> On 17 Nov 2016, at 20:14, Adrian Zubarev via swift-evolution 
> <[email protected]> wrote:
> 
> Dear Swift community,
> 
> while building a framework for BSON I had the following idea.
> 
> Here is a snippet of some code I do have in my module:
> 
> extension Array where Element == Document.Value {
>          
>     public func double(at index: Int) -> Double? {
>          
>         guard self.startIndex <= index && index < self.endIndex else { return 
> nil }
>          
>         if case .double(let double) = self[index] {
>              
>             return double
>         }
>         return nil
>     }
>      
>     …
> }
> This function is used to query the array and check if the element at the 
> given index is of a specific type. Now I would like also to implement a 
> semi-schema setter.
> 
> The problem that I see, is the ugliness of the subscript I’d create.
> 
> Currently the code would read nicely let d = array.double(at: 42), but after 
> change to a subscript the API would look odd array[doubleAt: 42] = 5.0.
> 
> Don’t get me wrong here, I also have methods with larger names like public 
> func scopedJavaScript(at index: Int) -> …. You can easily imagine that such 
> subscripts would look ugly array[scopedJavaScriptAt: 123] = ….
> 
> I propose to align the design of subscript with functions where one could 
> optionally give subscript a name.
> 
> func name(label parameter: Type) -> ReturnType
> 
> subscript optionalName(label parameter: Type) -> ReturnType
> This change would make my API nice and clean. array.scopedJavaScript[at: 213] 
> = …
> 
> This also might be the opportunity to rethink the labeling rule on 
> subscripts, but this shall not be the main focus of this pitch.
> 
> 
> 
> 
> -- 
> Adrian Zubarev
> Sent with Airmail
> 
> _______________________________________________
> swift-evolution mailing list
> [email protected] <mailto:[email protected]>
> https://lists.swift.org/mailman/listinfo/swift-evolution 
> <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