And revised with feedback: Modernizing Attribute Cases and Argument Naming <https://gist.github.com/erica/29c1a7fb7f49324d572f>
This discussion seems to be drawing to a natural close, so please let me know if there are any gaping issues that remain as well as any quibbles. Thank you, -- Erica
Modernizing Attribute Case and Attribute Argument Naming
Author(s): Erica Sadun <http://github.com/erica>
Review manager: TBD
Two isolated instances of snake case <https://en.wikipedia.org/wiki/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 <http://article.gmane.org/gmane.comp.lang.swift.evolution/7335> 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 mutable_variant argument. 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.
<https://gist.github.com/erica/29c1a7fb7f49324d572f#detail-design-updating-the-mutable_variant-argument>Detail Design: Updating the mutable_variant argument
The mutable_variant argument refactor is minimal. It should use the lower camel case Swift standard for arguments and be renamed mutableVariant.
<https://gist.github.com/erica/29c1a7fb7f49324d572f#detail-design-updating-the-warn_unused_result-attribute>Detail Design: Updating the warn_unused_result attribute
In the current version of Swift, most native attributes use lowercase naming: for example @testable and noescape. The most natural approach is to mimic this with @warn-unused-result, namely @warnunusedresult.
While this lower case pattern matches other compound attribute examples: objc, noescape, nonobjc, and 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: UIApplicationMain, NSManaged, NSCopying, NSApplicationMain, IBAction, IBDesignable, IBInspectable, and 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:
public func sort() -> [Self.Generator.Element]
This is the proposed public declaration of sort() in Swift 3.0:
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 <https://github.com/apple/swift-evolution/blob/master/proposals/0030-property-behavior-decls.md> proposal introduces property implementation patterns using attributes to declare behavior function names, for example: @lazy and @deferred.
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 @Swift.Autoclosure, @UIKit.UIApplicationMain, @UIKit.IBOutlet, @Swift.NoReturn, @StdLib.lazy, @Custom.deferred, etc.
@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 print function (print a view) from Swift's (output to the console or custom stream).
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 UIApplicationMain, NSManaged, NSCopying, NSApplicationMain, IBAction, IBDesignable, IBInspectable, and IBOutlet
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"
On Feb 19, 2016, at 4:31 PM, Brent Royal-Gordon <firstname.lastname@example.org> wrote:
* There are Swift attributes: @autoclosure, @available, @objc, @noescape, @nonobjc, @noreturn, @testable, @warn-unused-result, @convention, @noreturn.
* There are ObjC-ish/Xcode-ish attributes: @UIApplicationMain, @NSManaged, @NSCopying, @NSApplicationMain, @IBAction, @IBDesignable, @IBInspectable, @IBOutlet
* There may be user-definable attributes under SE-0030: for example @lazy, @delayed; these are certainly attribute-ish, and it makes sense to present these using attribute-syntax.
* The attribute syntax using `@` has had an intention "to open the space up to user attributes at some point"
I don't think this is a problem in and of itself. All the things that can come after an @ are attributes; behaviors allow you to declare your own attributes with a (small, but hopefully growing over time) subset of the full attribute semantics.
If Swift were to start accepting user-defined attributes, it would need some way to differentiate and namespace potential conflicts. The most obvious solution looks like this:
`@Swift.autoclosure`, `@UIKit.UIApplicationMain`, `@UIKit.IBOutlet`, `@Swift.noreturn`, `@Custom.lazy`, etc.
Cumbersome, ugly, problematic.
This *is* cumbersome and ugly, but so is `Foundation.NSArray`. You only fully qualify identifiers when the extra precision is necessary. Sure, it means you should try to give behaviors names that don't conflict with modules you're likely to work with (including the standard library), but this is already true of all Swift global symbols, including top-level type names. So I don't think this is problematic at all.
(Incidentally, I assume that `@Custom.lazy` comes from a module called "Custom", not that "Custom" is a prefix for all behaviors.)