Static Subscript


(David Sweeris) #1

What do we think about allowing types to have static subscripts?
struct Foo {
    static subscript(bar: Bar) -> FooBar {...}
}

It could be used to implement umbrella class “initializers” that return subclasses (or anything, really) without relying on Objective-C tomfoolery, since it’s just another function and can return anything you want:
class Int8Class : SwiftInteger {…}
class Int16Class : SwiftInteger { var x: Int16; override init() { self.x = 0 }; init(_ x: Int16) { self.x = x } }
class Int32Class : SwiftInteger {…}
class IntClass : SwiftInteger {…}
class BigIntClass : SwiftInteger {…}
class SwiftInteger {
    static subscript() -> SwiftInteger {…}
    static subscript(x: Int8) -> SwiftInteger {…}
    static subscript(x: Int16) -> SwiftInteger {…}
    static subscript(x: Int32) -> SwiftInteger {…}
    static subscript(x: Int) -> SwiftInteger {
        switch x {
        case Int( Int8.min)...Int( Int8.max): return Int8Class(Int8(x))
        case Int(Int16.min)...Int(Int16.max): return Int16Class(Int16(x))
        case Int(Int32.min)...Int(Int32.max): return Int32Class(Int32(x))
        default: return IntClass(x)
        }
    }
}
let foo = SwiftInteger[256] //foo is a Int16Class

Or for creating “functions” that have properties:
struct add {
    static let name: String = "add"
    static var logging = false
    static private (set) var callCount = 0
    static subscript(arg1: Int, arg2: Int) -> Int {
        defer {
            if add.logging == true {
                print("callcount = \(add.callCount): \(add.name)(\(arg1), \(arg2)) -> \(ret)")
            }
        }
        add.callCount += 1
        let ret = arg1 + arg2
        return ret
    }
}
let nine = add[4, 5]
add.logging = true
let ten = add[4, 6] // prints “call count = 2: add(4, 6) -> 10"

Thoughts?

- Dave Sweeris


(Félix Cloutier) #2

I don't like that the subscript essentially becomes a second call syntax. Can we solve these problems in a different way?

Félix

···

Le 28 janv. 2016 à 22:20:01, Dave via swift-evolution <swift-evolution@swift.org> a écrit :

What do we think about allowing types to have static subscripts?
struct Foo {
    static subscript(bar: Bar) -> FooBar {...}
}

It could be used to implement umbrella class “initializers” that return subclasses (or anything, really) without relying on Objective-C tomfoolery, since it’s just another function and can return anything you want:
class Int8Class : SwiftInteger {…}
class Int16Class : SwiftInteger { var x: Int16; override init() { self.x = 0 }; init(_ x: Int16) { self.x = x } }
class Int32Class : SwiftInteger {…}
class IntClass : SwiftInteger {…}
class BigIntClass : SwiftInteger {…}
class SwiftInteger {
    static subscript() -> SwiftInteger {…}
    static subscript(x: Int8) -> SwiftInteger {…}
    static subscript(x: Int16) -> SwiftInteger {…}
    static subscript(x: Int32) -> SwiftInteger {…}
    static subscript(x: Int) -> SwiftInteger {
        switch x {
        case Int( Int8.min)...Int( Int8.max): return Int8Class(Int8(x))
        case Int(Int16.min)...Int(Int16.max): return Int16Class(Int16(x))
        case Int(Int32.min)...Int(Int32.max): return Int32Class(Int32(x))
        default: return IntClass(x)
        }
    }
}
let foo = SwiftInteger[256] //foo is a Int16Class

Or for creating “functions” that have properties:
struct add {
    static let name: String = "add"
    static var logging = false
    static private (set) var callCount = 0
    static subscript(arg1: Int, arg2: Int) -> Int {
        defer {
            if add.logging == true {
                print("callcount = \(add.callCount): \(add.name)(\(arg1), \(arg2)) -> \(ret)")
            }
        }
        add.callCount += 1
        let ret = arg1 + arg2
        return ret
    }
}
let nine = add[4, 5]
add.logging = true
let ten = add[4, 6] // prints “call count = 2: add(4, 6) -> 10"

Thoughts?

- Dave Sweeris

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Jessy) #3

+1 to this; static subscripts are sometimes the best way to express ideas. If static properties exist, so should subscripts.


(David Sweeris) #4

I don't like it either, as the "official" way to get that functionality, but that's not what I was suggesting. Those were just a couple off-top-of-my-head examples of what could be done if we had them.

They could also be used to facilitate "static sequences":
protocol StaticSequenceType {
// whatever's in SequenceType, but with "static" in front of everything
}
And then with a minor change to the "for-in" mechanism, this would become valid:
for foo in SomeType {
// do stuff
}

(Come to think of it, seems like that could help with the proposal to be able to iterate over all cases of an enum, since it'd probably decrease the chances of a naming collision between pre-existing properties and the automatically created code.)

Anyway, unless I'm misunderstanding your objection, aside from "letting people do something in an unaesthetic way", I can't really think of a downside.

Does anyone know why they're currently disallowed?

- Dave Sweeris

···

On Jan 28, 2016, at 19:36, Félix Cloutier <felixcca@yahoo.ca> wrote:

I don't like that the subscript essentially becomes a second call syntax. Can we solve these problems in a different way?

Félix

Le 28 janv. 2016 à 22:20:01, Dave via swift-evolution <swift-evolution@swift.org> a écrit :

What do we think about allowing types to have static subscripts?
struct Foo {
    static subscript(bar: Bar) -> FooBar {...}
}

It could be used to implement umbrella class “initializers” that return subclasses (or anything, really) without relying on Objective-C tomfoolery, since it’s just another function and can return anything you want:
class Int8Class : SwiftInteger {…}
class Int16Class : SwiftInteger { var x: Int16; override init() { self.x = 0 }; init(_ x: Int16) { self.x = x } }
class Int32Class : SwiftInteger {…}
class IntClass : SwiftInteger {…}
class BigIntClass : SwiftInteger {…}
class SwiftInteger {
    static subscript() -> SwiftInteger {…}
    static subscript(x: Int8) -> SwiftInteger {…}
    static subscript(x: Int16) -> SwiftInteger {…}
    static subscript(x: Int32) -> SwiftInteger {…}
    static subscript(x: Int) -> SwiftInteger {
        switch x {
        case Int( Int8.min)...Int( Int8.max): return Int8Class(Int8(x))
        case Int(Int16.min)...Int(Int16.max): return Int16Class(Int16(x))
        case Int(Int32.min)...Int(Int32.max): return Int32Class(Int32(x))
        default: return IntClass(x)
        }
    }
}
let foo = SwiftInteger[256] //foo is a Int16Class

Or for creating “functions” that have properties:
struct add {
    static let name: String = "add"
    static var logging = false
    static private (set) var callCount = 0
    static subscript(arg1: Int, arg2: Int) -> Int {
        defer {
            if add.logging == true {
                print("callcount = \(add.callCount): \(add.name)(\(arg1), \(arg2)) -> \(ret)")
            }
        }
        add.callCount += 1
        let ret = arg1 + arg2
        return ret
    }
}
let nine = add[4, 5]
add.logging = true
let ten = add[4, 6] // prints “call count = 2: add(4, 6) -> 10"

Thoughts?

- Dave Sweeris

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution