[Discussion] Using dot prefixes to infer non-enumeration static members


(Erica Sadun) #1

While discussing leading enumeration dot prefixes, Howard Lovatt asked why static properties and methods could not be inferred via a dot prefix as well. Based on Swift-Evolution conventions, here's a new thread to discuss this idea: specifically, would it be beneficial (and/or possible) to use dot prefixes to denote static member references in instance member code.

Howard wrote:

+1 for the proposal, it is wierd to use `.` in some places and not others.

On the subject of static methods and properties in general, would it be possible for `.name` to be a reference to a static and `name` a reference to an instance? EG:

    .name = x // static
    name = x // instance
    x = name + .name // instance + static
    r = name ... .name // instance ... static, needs space
    r = name...Type.name // Can still qualify with type name

Under the current system, you must explicitly name or derive a type to access static members from instance member implementations.

struct MyStruct {
    static func staticMember() {}
    
    func instanceMember() {
        // name a type
        MyStruct.staticMember() // works

        // derive a type
        self.dynamicType.staticMember() // works
        
        // error: value of tuple type '()' has no member 'staticMember'
        // does not work
        .staticMember()
    }
}

Using dot prefixes for static member access:

* Has precedent in enumeration members
* Would streamline Swift code
* Is visually differentiated from `self`-prefixed instance member references

What are your thoughts, both technical and philosophical, on a change like this? Thanks in advance for your feedback.

-- Erica


(Jordan Rose) #2

Dot-prefixed member expressions are currently looked up as static members of the contextual type, which lets you do things like this:

import AppKit
let colors: [NSColor] = [.redColor(), .blueColor()]

I don't think we want to change or overload that rule to also look up static members of the enclosing lexical context type (i.e. the type of 'self').

Jordan

···

On Feb 15, 2016, at 8:58, Erica Sadun via swift-evolution <swift-evolution@swift.org> wrote:

While discussing leading enumeration dot prefixes, Howard Lovatt asked why static properties and methods could not be inferred via a dot prefix as well. Based on Swift-Evolution conventions, here's a new thread to discuss this idea: specifically, would it be beneficial (and/or possible) to use dot prefixes to denote static member references in instance member code.

Howard wrote:

+1 for the proposal, it is wierd to use `.` in some places and not others.

On the subject of static methods and properties in general, would it be possible for `.name` to be a reference to a static and `name` a reference to an instance? EG:

    .name = x // static
    name = x // instance
    x = name + .name // instance + static
    r = name ... .name // instance ... static, needs space
    r = name...Type.name // Can still qualify with type name

Under the current system, you must explicitly name or derive a type to access static members from instance member implementations.

struct MyStruct {
    static func staticMember() {}
    
    func instanceMember() {
        // name a type
        MyStruct.staticMember() // works

        // derive a type
        self.dynamicType.staticMember() // works
        
        // error: value of tuple type '()' has no member 'staticMember'
        // does not work
        .staticMember()
    }
}

Using dot prefixes for static member access:

* Has precedent in enumeration members
* Would streamline Swift code
* Is visually differentiated from `self`-prefixed instance member references

What are your thoughts, both technical and philosophical, on a change like this? Thanks in advance for your feedback.


#3

Not sure if it’s valid concern, but the current shorthand is based on the immediate context of comparison/pattern matching. Adding shorthand here for static member reference within the class could introduce some resolution conflicts.

enum MyEnum {
    case one
    case two
    
    static func stillOne() -> MyEnum { return one }
}

let data:MyEnum = .one
if .stillOne() == data { print("Something!") }

struct MyStruct {
    static var data:MyEnum = .one
    static func stillOne() -> Bool { return data == .one }
    
    func instanceMember() {
        if .stillOne() == MyStruct.data { print("Something") } // This currently work
    }
}

The current logic easily resolves the code inside instanceMember() as a shorthand to MyEnum, but if we expand the shorthand as describe, will it make it too hard on the compiler.

Dany

···

Le 15 févr. 2016 à 11:58, Erica Sadun via swift-evolution <swift-evolution@swift.org> a écrit :

While discussing leading enumeration dot prefixes, Howard Lovatt asked why static properties and methods could not be inferred via a dot prefix as well. Based on Swift-Evolution conventions, here's a new thread to discuss this idea: specifically, would it be beneficial (and/or possible) to use dot prefixes to denote static member references in instance member code.

Howard wrote:

+1 for the proposal, it is wierd to use `.` in some places and not others.

On the subject of static methods and properties in general, would it be possible for `.name` to be a reference to a static and `name` a reference to an instance? EG:

    .name = x // static
    name = x // instance
    x = name + .name // instance + static
    r = name ... .name // instance ... static, needs space
    r = name...Type.name // Can still qualify with type name

Under the current system, you must explicitly name or derive a type to access static members from instance member implementations.

struct MyStruct {
    static func staticMember() {}
    
    func instanceMember() {
        // name a type
        MyStruct.staticMember() // works

        // derive a type
        self.dynamicType.staticMember() // works
        
        // error: value of tuple type '()' has no member 'staticMember'
        // does not work
        .staticMember()
    }
}

Using dot prefixes for static member access:

* Has precedent in enumeration members
* Would streamline Swift code
* Is visually differentiated from `self`-prefixed instance member references

What are your thoughts, both technical and philosophical, on a change like this? Thanks in advance for your feedback.


(Erica Sadun) #4

Sounds like a compelling response to me. Thanks, Jordan.

-- E

···

On Feb 15, 2016, at 11:40 AM, Jordan Rose <jordan_rose@apple.com> wrote:

On Feb 15, 2016, at 8:58, Erica Sadun via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

While discussing leading enumeration dot prefixes, Howard Lovatt asked why static properties and methods could not be inferred via a dot prefix as well. Based on Swift-Evolution conventions, here's a new thread to discuss this idea: specifically, would it be beneficial (and/or possible) to use dot prefixes to denote static member references in instance member code.

Howard wrote:

+1 for the proposal, it is wierd to use `.` in some places and not others.

On the subject of static methods and properties in general, would it be possible for `.name` to be a reference to a static and `name` a reference to an instance? EG:

    .name = x // static
    name = x // instance
    x = name + .name // instance + static
    r = name ... .name // instance ... static, needs space
    r = name...Type.name // Can still qualify with type name

Under the current system, you must explicitly name or derive a type to access static members from instance member implementations.

struct MyStruct {
    static func staticMember() {}
    
    func instanceMember() {
        // name a type
        MyStruct.staticMember() // works

        // derive a type
        self.dynamicType.staticMember() // works
        
        // error: value of tuple type '()' has no member 'staticMember'
        // does not work
        .staticMember()
    }
}

Using dot prefixes for static member access:

* Has precedent in enumeration members
* Would streamline Swift code
* Is visually differentiated from `self`-prefixed instance member references

What are your thoughts, both technical and philosophical, on a change like this? Thanks in advance for your feedback.

Dot-prefixed member expressions are currently looked up as static members of the contextual type, which lets you do things like this:

import AppKit
let colors: [NSColor] = [.redColor(), .blueColor()]

I don't think we want to change or overload that rule to also look up static members of the enclosing lexical context type (i.e. the type of 'self').

Jordan


(Howard Lovatt) #5

@Jordan,

You said "I don't think we want to change or overload that rule to also
look up static members of the *enclosing lexical context type* (i.e. the
type of 'self')." But you do already; inside an enum, e.g.:

enum Enum {
    case one
    case two
    func e() -> String {
        if self == .one {
            return "one"
        } else if self == .two {
            return "two"
        }
        return "unkown"
    }
}

Compared to inside a static:

class Static {
    class One: Static {}
    static let one = One()
    class Two: Static {}
    static let two = Two()
    func e() -> String {
        if self === Static.one {
            return "one"
        } else if self === Static.two {
            return "two"
        }
        return "unknown"
    }
}

Why so different? The enum version looks inside the type `Enum` to find
`.one` and `.two`, but the static version doesn't look inside the type
`Static` and hence you have to say `Static.one` and `Static.two` :frowning:

  -- Howard.

···

On 16 February 2016 at 05:40, Jordan Rose via swift-evolution < swift-evolution@swift.org> wrote:

On Feb 15, 2016, at 8:58, Erica Sadun via swift-evolution < > swift-evolution@swift.org> wrote:

While discussing leading enumeration dot prefixes, Howard Lovatt asked why
static properties and methods could not be inferred via a dot prefix as
well. Based on Swift-Evolution conventions, here's a new thread to discuss
this idea: specifically, would it be beneficial (and/or possible) to use
dot prefixes to denote static member references in instance member code.

Howard wrote:

+1 for the proposal, it is wierd to use `.` in some places and not others.

On the subject of static methods and properties in general, would it be
possible for `.name` to be a reference to a static and `name` a reference
to an instance? EG:

    .name = x // static
    name = x // instance
    x = name + .name // instance + static
    r = name ... .name // instance ... static, needs space
    r = name...Type.name // Can still qualify with type name

Under the current system, you must explicitly name or derive a type to
access static members from instance member implementations.

struct MyStruct {
    static func staticMember() {}

    func instanceMember() {
        // name a type
        MyStruct.staticMember() // works

        // derive a type
        self.dynamicType.staticMember() // works

        // error: value of tuple type '()' has no member 'staticMember'
        // does not work
        .staticMember()
    }
}

Using dot prefixes for static member access:

* Has precedent in enumeration members
* Would streamline Swift code
* Is visually differentiated from `self`-prefixed instance member
references

What are your thoughts, both technical and philosophical, on a change like
this? Thanks in advance for your feedback.

Dot-prefixed member expressions are currently looked up as static members
of the* contextual type,* which lets you do things like this:

import AppKit
let colors: [NSColor] = [.redColor(), .blueColor()]

I don't think we want to change or overload that rule to also look up
static members of the *enclosing lexical context type* (i.e. the type of
'self').

Jordan

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


(Jordan Rose) #6

That works just as well outside the enum:

enum Enum {
    case one
    case two
}
func e(value: Enum) -> String {
    if value == .one {
        return "one"
    } else if value == .two {
        return "two"
    }
    return "unkown"
}

Here it's looking in the contextual type provided by ==. The enum synthesizes a function along the lines of

func ==(a: Enum, b: Enum)

This doesn't work for === because you can compare identity across class types.

func ===(a: AnyObject, b: AnyObject)

Jordan

···

On Feb 16, 2016, at 16:20, Howard Lovatt <howard.lovatt@gmail.com> wrote:

@Jordan,

You said "I don't think we want to change or overload that rule to also look up static members of the enclosing lexical context type (i.e. the type of 'self')." But you do already; inside an enum, e.g.:

enum Enum {
    case one
    case two
    func e() -> String {
        if self == .one {
            return "one"
        } else if self == .two {
            return "two"
        }
        return "unkown"
    }
}
Compared to inside a static:

class Static {
    class One: Static {}
    static let one = One()
    class Two: Static {}
    static let two = Two()
    func e() -> String {
        if self === Static.one {
            return "one"
        } else if self === Static.two {
            return "two"
        }
        return "unknown"
    }
}
Why so different? The enum version looks inside the type `Enum` to find `.one` and `.two`, but the static version doesn't look inside the type `Static` and hence you have to say `Static.one` and `Static.two` :frowning:

  -- Howard.

On 16 February 2016 at 05:40, Jordan Rose via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

On Feb 15, 2016, at 8:58, Erica Sadun via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

While discussing leading enumeration dot prefixes, Howard Lovatt asked why static properties and methods could not be inferred via a dot prefix as well. Based on Swift-Evolution conventions, here's a new thread to discuss this idea: specifically, would it be beneficial (and/or possible) to use dot prefixes to denote static member references in instance member code.

Howard wrote:

+1 for the proposal, it is wierd to use `.` in some places and not others.

On the subject of static methods and properties in general, would it be possible for `.name` to be a reference to a static and `name` a reference to an instance? EG:

    .name = x // static
    name = x // instance
    x = name + .name // instance + static
    r = name ... .name // instance ... static, needs space
    r = name...Type.name // Can still qualify with type name

Under the current system, you must explicitly name or derive a type to access static members from instance member implementations.

struct MyStruct {
    static func staticMember() {}
    
    func instanceMember() {
        // name a type
        MyStruct.staticMember() // works

        // derive a type
        self.dynamicType.staticMember() // works
        
        // error: value of tuple type '()' has no member 'staticMember'
        // does not work
        .staticMember()
    }
}

Using dot prefixes for static member access:

* Has precedent in enumeration members
* Would streamline Swift code
* Is visually differentiated from `self`-prefixed instance member references

What are your thoughts, both technical and philosophical, on a change like this? Thanks in advance for your feedback.

Dot-prefixed member expressions are currently looked up as static members of the contextual type, which lets you do things like this:

import AppKit
let colors: [NSColor] = [.redColor(), .blueColor()]

I don't think we want to change or overload that rule to also look up static members of the enclosing lexical context type (i.e. the type of 'self').

Jordan

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


(Howard Lovatt) #7

Hi Jordan,

Yes implementing `==` will patch the example I gave, but it isn't a general
solution. Consider this variation:

class Static: Equatable {
    class One: Static {}
    static let one = One()
    class Two: Static {}
    static let two = Two()
    func e() -> String {
        switch self {
        case Static.one:
            return "one"
        case Static.two :
            return "two"
        default:
            return "unknown"
        }
    }
}
func ==(lhs: Static, rhs: Static) -> Bool {
    return lhs === rhs
}

Still needs the type qualifiers :(.

  -- Howard.

···

On 17 February 2016 at 11:31, Jordan Rose <jordan_rose@apple.com> wrote:

That works just as well outside the enum:

enum Enum {
    case one
    case two
}

func e(value: Enum) -> String {
    if value == .one {
        return "one"
    } else if value == .two {
        return "two"
    }
    return "unkown"
}

Here it's looking in the contextual type provided by ==. The enum
synthesizes a function along the lines of

func ==(a: Enum, b: Enum)

This doesn't work for === because you can compare identity across class
types.

func ===(a: AnyObject, b: AnyObject)

Jordan

On Feb 16, 2016, at 16:20, Howard Lovatt <howard.lovatt@gmail.com> wrote:

@Jordan,

You said "I don't think we want to change or overload that rule to also
look up static members of the *enclosing lexical context type* (i.e. the
type of 'self')." But you do already; inside an enum, e.g.:

enum Enum {
    case one
    case two
    func e() -> String {
        if self == .one {
            return "one"
        } else if self == .two {
            return "two"
        }
        return "unkown"
    }
}

Compared to inside a static:

class Static {
    class One: Static {}
    static let one = One()
    class Two: Static {}
    static let two = Two()
    func e() -> String {
        if self === Static.one {
            return "one"
        } else if self === Static.two {
            return "two"
        }
        return "unknown"
    }
}

Why so different? The enum version looks inside the type `Enum` to find
`.one` and `.two`, but the static version doesn't look inside the type
`Static` and hence you have to say `Static.one` and `Static.two` :frowning:

  -- Howard.

On 16 February 2016 at 05:40, Jordan Rose via swift-evolution < > swift-evolution@swift.org> wrote:

On Feb 15, 2016, at 8:58, Erica Sadun via swift-evolution < >> swift-evolution@swift.org> wrote:

While discussing leading enumeration dot prefixes, Howard Lovatt asked
why static properties and methods could not be inferred via a dot prefix as
well. Based on Swift-Evolution conventions, here's a new thread to discuss
this idea: specifically, would it be beneficial (and/or possible) to use
dot prefixes to denote static member references in instance member code.

Howard wrote:

+1 for the proposal, it is wierd to use `.` in some places and not
others.

On the subject of static methods and properties in general, would it be
possible for `.name` to be a reference to a static and `name` a reference
to an instance? EG:

    .name = x // static
    name = x // instance
    x = name + .name // instance + static
    r = name ... .name // instance ... static, needs space
    r = name...Type.name // Can still qualify with type name

Under the current system, you must explicitly name or derive a type to
access static members from instance member implementations.

struct MyStruct {
    static func staticMember() {}

    func instanceMember() {
        // name a type
        MyStruct.staticMember() // works

        // derive a type
        self.dynamicType.staticMember() // works

        // error: value of tuple type '()' has no member 'staticMember'
        // does not work
        .staticMember()
    }
}

Using dot prefixes for static member access:

* Has precedent in enumeration members
* Would streamline Swift code
* Is visually differentiated from `self`-prefixed instance member
references

What are your thoughts, both technical and philosophical, on a change
like this? Thanks in advance for your feedback.

Dot-prefixed member expressions are currently looked up as static members
of the* contextual type,* which lets you do things like this:

import AppKit
let colors: [NSColor] = [.redColor(), .blueColor()]

I don't think we want to change or overload that rule to also look up
static members of the *enclosing lexical context type* (i.e. the type of
'self').

Jordan

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


(Jordan Rose) #8

No, I meant the code I showed already works by the principle I stated. Dot-prefixed member access always looks up in a contextual type for a member returning the same type. Your example here has nothing to do about lexical scoping; it just means we don't take subtypes into account when we could.

Jordan

···

On Feb 16, 2016, at 16:59, Howard Lovatt <howard.lovatt@gmail.com> wrote:

Hi Jordan,

Yes implementing `==` will patch the example I gave, but it isn't a general solution. Consider this variation:

class Static: Equatable {
    class One: Static {}
    static let one = One()
    class Two: Static {}
    static let two = Two()
    func e() -> String {
        switch self {
        case Static.one:
            return "one"
        case Static.two :
            return "two"
        default:
            return "unknown"
        }
    }
}
func ==(lhs: Static, rhs: Static) -> Bool {
    return lhs === rhs
}

Still needs the type qualifiers :(.

  -- Howard.

On 17 February 2016 at 11:31, Jordan Rose <jordan_rose@apple.com <mailto:jordan_rose@apple.com>> wrote:
That works just as well outside the enum:

enum Enum {
    case one
    case two
}
func e(value: Enum) -> String {
    if value == .one {
        return "one"
    } else if value == .two {
        return "two"
    }
    return "unkown"
}

Here it's looking in the contextual type provided by ==. The enum synthesizes a function along the lines of

func ==(a: Enum, b: Enum)

This doesn't work for === because you can compare identity across class types.

func ===(a: AnyObject, b: AnyObject)

Jordan

On Feb 16, 2016, at 16:20, Howard Lovatt <howard.lovatt@gmail.com <mailto:howard.lovatt@gmail.com>> wrote:

@Jordan,

You said "I don't think we want to change or overload that rule to also look up static members of the enclosing lexical context type (i.e. the type of 'self')." But you do already; inside an enum, e.g.:

enum Enum {
    case one
    case two
    func e() -> String {
        if self == .one {
            return "one"
        } else if self == .two {
            return "two"
        }
        return "unkown"
    }
}
Compared to inside a static:

class Static {
    class One: Static {}
    static let one = One()
    class Two: Static {}
    static let two = Two()
    func e() -> String {
        if self === Static.one {
            return "one"
        } else if self === Static.two {
            return "two"
        }
        return "unknown"
    }
}
Why so different? The enum version looks inside the type `Enum` to find `.one` and `.two`, but the static version doesn't look inside the type `Static` and hence you have to say `Static.one` and `Static.two` :frowning:

  -- Howard.

On 16 February 2016 at 05:40, Jordan Rose via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

On Feb 15, 2016, at 8:58, Erica Sadun via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

While discussing leading enumeration dot prefixes, Howard Lovatt asked why static properties and methods could not be inferred via a dot prefix as well. Based on Swift-Evolution conventions, here's a new thread to discuss this idea: specifically, would it be beneficial (and/or possible) to use dot prefixes to denote static member references in instance member code.

Howard wrote:

+1 for the proposal, it is wierd to use `.` in some places and not others.

On the subject of static methods and properties in general, would it be possible for `.name` to be a reference to a static and `name` a reference to an instance? EG:

    .name = x // static
    name = x // instance
    x = name + .name // instance + static
    r = name ... .name // instance ... static, needs space
    r = name...Type.name // Can still qualify with type name

Under the current system, you must explicitly name or derive a type to access static members from instance member implementations.

struct MyStruct {
    static func staticMember() {}
    
    func instanceMember() {
        // name a type
        MyStruct.staticMember() // works

        // derive a type
        self.dynamicType.staticMember() // works
        
        // error: value of tuple type '()' has no member 'staticMember'
        // does not work
        .staticMember()
    }
}

Using dot prefixes for static member access:

* Has precedent in enumeration members
* Would streamline Swift code
* Is visually differentiated from `self`-prefixed instance member references

What are your thoughts, both technical and philosophical, on a change like this? Thanks in advance for your feedback.

Dot-prefixed member expressions are currently looked up as static members of the contextual type, which lets you do things like this:

import AppKit
let colors: [NSColor] = [.redColor(), .blueColor()]

I don't think we want to change or overload that rule to also look up static members of the enclosing lexical context type (i.e. the type of 'self').

Jordan

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