Modernizing Attribute Case and Attribute Argument Naming
- Proposal: TBD
- Author(s): Erica Sadun
- Status: TBD
- Review manager: TBD
Two isolated instances of snake case remain in the Swift attribute grammar. This proposal updates those elements to bring them into compliance with modern Swift language standards and applies a new consistent pattern to existing attributes.
The Swift-Evolution discussion of this topic took place in the [Discussion] Modernizing Attribute Case and Attribute Argument Naming thread. Hat tip to Michael Well, Dmitri Gribenko, Brent Royal-Gordon, Shawn Erickson, Dany St-Amant
Two elements of Swift attribute grammar retain lower_snake_case patterns: Swift's
warn_unused_result attribute and its
This pattern is being actively eliminated from Swift in an effort to modernize
the language and adopt common naming patterns. Renaming these elements fall into
two separate problems: one trivial, one forward-looking.
Detail Design: Updating the
mutable_variant argument refactor is minimal. It should use the lower camel case Swift standard for arguments and be renamed
Detail Design: Updating the
In the current version of Swift, most native attributes use lowercase naming: for example
noescape. The most natural approach is to mimic this with
While this lower case pattern matches other compound attribute examples:
noreturn, the re-engineered version of
warnunusedresult is hard to read. It looks like a continuous string of lowercase characters instead of punching clear, identifiable semantic elements. Using lowercase for complex attributes names, including future names yet to be introduced into the language, becomes confusing when used with longer compound examples.
For this reason, I recommend the Swift team adopt an upper camel case convention for attributes, matching the existing Cocoa participants:
IBOutlet. This approach avoids the otherwise confusing long name issue.
The renamed elements look like this:
@Autoclosure // was @autoclosure @Available // was @available @ObjC // was @objc @NoEscape // was @noescape @NonObjC // was @nonobjc @NoReturn // was @noreturn @Testable // was @testable @WarnUnusedResult // was @warn-unused-result @Convention // was @convention @NoReturn // was @noreturn
Here is the public declaration of
sort() in Swift 2.2:
@warn_unused_result(mutable_variant="sortInPlace") public func sort() -> [Self.Generator.Element]
This is the proposed public declaration of
sort() in Swift 3.0:
@WarnUnusedResult(mutableVariant: "sortInPlace") public func sort() -> [Self.Generator.Element]
This revised example uses an argument colon (as proposed in "Replacing Equal Signs with Colons For Attribute Arguments") rather than the equal sign currently specified in Swift 2.2
Joe Groff's Swift-Evolution SE-0030 Property Behaviors proposal introduces property implementation patterns using attributes to declare behavior function names, for example:
If Swift were to start accepting user-defined attributes, it needs a way to differentiate potential conflicts. The most obvious solution uses namespacing, for example
@AttributeName // built-in, upper camel case @attributename // or @attributeName, custom element that may not follow built-in patterns @Module.AttributeName // case follows source convention
Name collisions should be limited enough that fully-qualified attributes would be rare, as they already are with top-level calls such as differentiating NSView's
Joe Groff writes, "Once we open the floodgates for user-defined attributes, I think traditional namespacing and name lookup makes a lot of sense. We could conceptually namespace the existing hardcoded attributes into appropriate modules (Swift for the platform-neutral stuff, Foundation/AppKit/UIKit as appropriate for Apple-y stuff)."
Reaction to upper-case naming has been mixed. I personally believe the redesign is more readable. Others object to using uppercase outside of types, even though Cocoa imports are already doing so. Although the Swift team might prefer using lower camel case
@autoClosure, @available, @objC, @noEscape, @nonObjC, @noReturn, @testable, @warnUnusedResult, @convention, @noReturn but this would be out of step with non-native Swift attributes, specifically
Dany St-Amant suggests that attributes be case-insensitive, enabling coders to choose their casing. "[Maybe] cases could be ignored, making everybody writing code happy, and everyone reading code of others unhappy"