[swift-evolution] [Proposal] Eliminating Swift's Screaming Snake Case Identifiers

Erica Sadun erica at ericasadun.com
Wed Jan 27 16:56:34 CST 2016


Modernizing Swift's Debugging Identifiers

Proposal: TBD
Author(s): Erica Sadun <http://github.com/erica>
Status: TBD
Review manager: TBD
 <https://gist.github.com/erica/8b8c7eb841da39ac47c7#introduction>Introduction

This proposal aims to eliminate Swift's use of "screaming snake case <https://en.wikipedia.org/wiki/Snake_case>" like __FILE__ and __FUNCTION__ and replacing identifier instances with common octothorpe-prefixed <https://en.wiktionary.org/wiki/octothorpe> lower camel case <https://en.wikipedia.org/wiki/CamelCase> #identifier representations.

The Swift-Evolution discussion of this topic took place in the "[Review] SE-0022: Referencing the Objective-C selector of a method" thread and then in its own "[Proposal] Eliminating Swift's Screaming Snake Case Identifiers" thread

 <https://gist.github.com/erica/8b8c7eb841da39ac47c7#motivation>Motivation

Swift's pre-processor offers built-in __FILE__, __LINE__, __COLUMN__, and __FUNCTION__ identifiers. These expand to string and integer literals corresponding to a current location in source code. This feature provides high utility for logging, both tracing execution through logged messages and enabling developers to capture error context <http://ericasadun.com/2015/08/27/capturing-context-swiftlang/>.

The current identifiers owe their syntax to C's __FILE__ and __LINE__ macros. These are built into C's preprocessor and expanded before running the C-language parser. Swift's implementation differs from C's but offers similar functionality and, unfortunately, similar symbols. This proposal aims to break free of the historic chains of their unsightly screaming camel case, which look like boa constrictors trying to digest <https://s-media-cache-ak0.pinimg.com/originals/59/ea/ee/59eaee788c31463b70e6e3d4fca5508f.jpg> fully swallowed keywords.

 <https://gist.github.com/erica/8b8c7eb841da39ac47c7#proposed-solution>Proposed solution

Using octothorpe-prefixed keywords offers several advantages:

They match the existing #available keyword (D. Gregor)
They match SE-0022's already-accepted #selector(...) approach that reference a method's Objective-C selector (D. Gregor)
They support targeted code completion (D. Gregor)
They add a compiler-supported expression type that doesn't steal keywords, introducing a convention where # means "invoke compiler substitution logic here" (J. Rose)
They'd provide short-term solutions for a yet-as-undesigned macro system (D. Gregor)
 <https://gist.github.com/erica/8b8c7eb841da39ac47c7#detailed-design>Detailed design

This proposal renames the following identifiers:

__FILE__ -> #file
__LINE__ -> #line
__COLUMN__ -> #column
__DSO_HANDLE__ -> #dso_handle
This proposal eliminates __FUNCTION__. It introduces #symbol, (e.g. Swift.Dictionary.Init(x:Int,y:String)), which summarizes context including module, type, and function. 

A fully qualified symbol enables users to access exactly the information they desire. 
It should contain parameter type information to properly identify member overloads.
Each identifier will still expand at the call site, ensuring that the behavior matches that from the current suite.

 <https://gist.github.com/erica/8b8c7eb841da39ac47c7#alternatives-considered>Alternatives Considered

 <https://gist.github.com/erica/8b8c7eb841da39ac47c7#sourcelocation>#sourceLocation

SR-198 <https://bugs.swift.org/browse/SR-198> requested the coalescing of the existing file, line, and function identifiers, potentially supporting a module representation as well. Andrew Bennett <https://bugs.swift.org/secure/ViewProfile.jspa?name=bnut> offered an initial design: 

public struct SourceLocation: CustomDebugStringConvertible {
    init(file: String = __FILE__, line: Int = __LINE__, column: Int = __COLUMN__, function: String = __FUNCTION__) {
        self.file = file
        self.line = line
        self.column = column
        self.function = function
    }

    public let file: String
    public let line: Int
    public let column: Int
    public let function: String

    public var debugDescription: String {
        return "\(function) @ \(file):\(line):\(column)"
    }
}
 <https://gist.github.com/erica/8b8c7eb841da39ac47c7#summarizing-with-context>Summarizing with #context

A #context identifier would provide a compound type to provide a common well-defined tuple or struct summary of the current context with addressable elements. Offering addressable elements with a single identifier provides clean implementation. It permits developers to customize output based on current build settings without having to decompose the #symbol identifier output in logging routines.

Choosing which elements to represent could be problematic. Chris Lattner writes, "Splitting out module, type, method, or other information is prone to issues given that we allow nesting of types, nesting of functions, and perhaps nesting of modules some day. Providing all of the different things that clients could want seems like a never-ending problem."

In support of addressable elements, Joseph Lord writes, "Module information would be useful for a logging library, possibly to print the information but possibly also to allow different log levels (e.g. info, debug, warning, error, criticalError) to be configured for each module in a project so that log spam is manageable and possibly adjustable at runtime."

In support of summaries, Remy Demerest writes, "[I] love the idea that source location would be one object that you can print to get the full story while still retaining the possibility to use each individual components as needed, which is probably the rarer case. I never find myself wanting only some of properties and usually don't include them simply because it takes longer to write the format properly, if I can get them all in one go it's certainly a win."

 <https://gist.github.com/erica/8b8c7eb841da39ac47c7#implementation-notes>Implementation notes

Although the octothorpe-delineated #line identifier already exists in Swift for resetting line numbers (J. Lawrence), context can distinguish between uses. Joe Groff writes, "I'd prefer to use #line for this, and constrain the use of the current #line directive by context; like Chris said, we could require it to be the first thing after a newline, or we could adopt the #line = ... syntax a few people suggested."


> On Jan 26, 2016, at 11:51 PM, Chris Lattner <clattner at apple.com> wrote:
> 
> 
>> On Jan 26, 2016, at 6:13 PM, Joseph Lord <joseph at human-friendly.com> wrote:
>> 
>> Module information would be useful for a logging library, possibly to print the information but possibly also to allow different log levels (e.g. info, debug, warning, error, criticalError) to be configured for each module in a project so that log spam is manageable and possibly adjustable at runtime. (I have a fuller logging idea but have noted it is the example of out of scope and decided not to argue at this point). 
> 
> Ok, but why can’t you split that off the front of the symbol name?  The advantage of providing a fully qualified symbol name is that it allows users of this feature to get exactly the information they want.  Unlike my suggestion below, it should also include parameter type information, so it can identify overloads properly.
> 
> Splitting out module, type, method, or other information is prone to issues given that we allow nesting of types, nesting of functions, and perhaps nesting of modules some day.  Providing all of the different things that clients could want seems like a never-ending problem.
> 
> -Chris
> 
>> 
>> Joseph
>> 
>> 
>>> On Jan 26, 2016, at 11:58 PM, Chris Lattner via swift-evolution <swift-evolution at swift.org> wrote:
>>> 
>>> 
>>>> On Jan 26, 2016, at 1:48 PM, Erica Sadun <erica at ericasadun.com> wrote:
>>>> 
>>>> What do you think of:
>>>> 
>>>> #file, #lineNumber, #column, #symbol (e.g. Swift.Dictionary.init), #module, #contextDictionary
>>>> 
>>>> and calling it a day?
>>>> 
>>>> * using contextDictionary allows expandability and can subsume all existing context elements, indexed presumably by the same names
>>>> * renaming function to symbol takes care of self.dynamicType as well
>>>> * file and lineNumbers are gimmes
>>>> * column is apparently well liked by some (not going to kick someone's dog on this)
>>>> * adding module fills a big hole.
>>>> 
>>>> No tuples for Doug, covers some of Chris's points.
>>> 
>>> I mentioned this in the pull request:
>>> 
>>> I'd suggest:
>>> (file: String, line: Int, column: Int, symbol: String)
>>> 
>>> Where symbol would be the fully qualified name like "Swift.Dictionary.init”.
>>> 
>>> 
>>> I’m curious to hear what Doug’s concern about using tuples are.  Also, what is the use-case for #module?
>>> 
>>> -Chris
>>> _______________________________________________
>>> swift-evolution mailing list
>>> swift-evolution at swift.org
>>> https://lists.swift.org/mailman/listinfo/swift-evolution
> 

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160127/46ef712e/attachment.html>


More information about the swift-evolution mailing list