Skip to content

Instantly share code, notes, and snippets.

@erica
Last active February 13, 2016 16:46
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save erica/e0b8a3a22ab716a19db4 to your computer and use it in GitHub Desktop.
Save erica/e0b8a3a22ab716a19db4 to your computer and use it in GitHub Desktop.

Requiring Leading Dot Prefixes for Enum Instance Member Implementations

Introduction

Enumeration cases are essentially static not instance type members. Unlike static members in structures and classes, enumeration cases can be mentioned in initializers and instance methods without referencing a fully qualified type. This makes little sense. In no other case can an instance implementation directly access a static member. This proposal introduces a rule that requires leading dots or fully qualified references (EnumType.caseMember) to provide a more consistent developer experience to clearly disambiguate static cases from instance members.

Discussion took place on the Swift Evolution mailing list in the [Discussion] Enum Leading Dot Prefixes thread. This proposal uses lowerCamelCase enumeration cases in compliance with current API Guideline Working Group guidance.

Motivation

Swift infers the enclosing type for a case on a developer's behalf when the use is unambiguously of a single enumeration type. Inference enables you to craft switch statements like this:

switch Coin() {
case .heads: print("Heads")
case .tails: print("Tails")
}

A leading dot has become a conventional shorthand for "enumeration case" across the language. When used internally in enum implementations, a leading dot is not required, nor is a type name to access the static case member. The following code is legal in Swift.

enum Coin {
    case heads, tails
    func printMe() {
        switch self {
        case heads: print("Heads")  // no leading dot
        case .tails: print("Tails") // leading dot
        }
        
        if self == heads {          // no leading dot
            print("This is a head")
        }
        
        if self == .tails {         // leading dot
            print("This is a tail")
        }
    }

    init() {
        let cointoss = arc4random_uniform(2) == 0
        self = cointoss ? .heads : tails // mix and match leading dots
    }
}

This quirk produces a language inconsistency that can confuse developers and contravenes the guiding Principle of Least Astonishment. We propose to mandate a leading dot. This brings case mentions into lock-step with conventions used to reference them outside of enumeration type implementations.

Detail Design

Under this rule, the compiler will require a leading dot for all case members. The change will not affect other static members, which require fully qualified references from instance methods and infer self from static methods.

enum Coin {
    case heads, tails
    static func doSomething() { print("Something") }
    static func staticFunc() { doSomething() } // does not require leading dot
    static func staticFunc2() { let foo = .tails } // requires leading dot, even in static function
    func instanceFunc() { self.dynamicType.doSomething() } // requires full qualification
    func otherFunc() { if self == .heads ... } // requires leading dot, also initializers

    /// ...
} 

Alternatives Considered

Other than leaving the status quo, the language could force instance members to refer to cases using a fully qualified type, as with other static members.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment