A few thoughts on Swift symbology

In Swift, ? is an identifier character and ⚽︎ is a legal operator. You can assign M_PI to π or construct an ° operator that says “treat this double as being sourced from degrees”

public let π = M_PI
postfix operator ° {}
postfix func °(degrees: Double) -> Double {
    return degrees * π / 180.0
}

Unicode support expands code to include a more flexible symbol set for development. The most obvious use case is regional. Swift’s Unicode internationalizes the language, enabling developers to establish  meaningful symbols appropriate to their native tongues.

“let 你好 = "你好世界”

 

Swift developers have a love-hate relationship with these symbols, as they can provide beneficial clarity at the cost of easy typing.

The character sets are extensive. While the operator characters are easily enumerated, the symbol ones are much larger. This gist iterates through the ranges listed in the Swift Programming Language. Each set consists of header characters (legal starting characters) and additional characters that can be added but not used to start an operator or symbol.

Some symbols map beautifully to existing mathematical constants (π and τ for example) and to operators such as those used in set mathematics. The SwiftExperimental stdlib source implements a suite of these:

infix operator ∪ { associativity left precedence 140 }
infix operator ∪= { associativity right precedence 90 assignment }
infix operator ∩ { associativity left precedence 150 }
infix operator ∩= { associativity right precedence 90 assignment }
infix operator ⨁ { associativity left precedence 140 }
infix operator ⨁= { associativity right precedence 90 assignment }
infix operator ∈ { associativity left precedence 130 }
infix operator ∉ { associativity left precedence 130 }
infix operator ⊂ { associativity left precedence 130 }
infix operator ⊄ { associativity left precedence 130 }
infix operator ⊆ { associativity left precedence 130 }
infix operator ⊈ { associativity left precedence 130 }
infix operator ⊃ { associativity left precedence 130 }
infix operator ⊅ { associativity left precedence 130 }
infix operator ⊇ { associativity left precedence 130 }
infix operator ⊉ { associativity left precedence 130 }

Other symbols and operators offer less compelling use-cases like this custom quarter of Pi (or eighth of pie) that I threw into a utility math file:

public let ? = π / 4.0

or this custom pick operator that selects n items from a set:

infix operator ⛏ {}
public func ⛏(set: Set<T>, count: Int) -> Set<T> {
    func rnd(i: Int) -> Int {return Int(arc4random_uniform(UInt32(i)))}
    var items = set, chosenItems: Set<T> = []
    (1...count).forEach { _ in
        let whichOne = items
            .startIndex.advancedBy(rnd(items.count))
        chosenItems
            .insert(items.removeAtIndex(whichOne))
    }
    return chosenItems
}

Set(["a", "b", "c", "d", "e"]) ⛏ 3 // pick 3 members

When pushing APIs beyond common keyboard characters, carefully consider usage. Symbols, no matter how pretty, can be ridiculously hard to type. Some such as • are easily typed on US keyboards (Alt-8) but may be more difficult to access on other global layouts.

While coding, you don’t want to continually have to cut and paste from your declarations or require the system Characters picker to complete writing each line of code:

Screen Shot 2016-01-13 at 12.08.45 PM

For in-house symbols, the System Preferences > Keyboard > Text pane offers simple text-replacement. In the following settings, when I type (chicken) in Xcode, OS X automatically replaces it with ?. For common, internal API symbols, that’s a trade-off many developers are willing to make.

Screen Shot 2016-01-13 at 12.09.06 PM

A more important question arises in what you expose for API consumption outside your immediate group, especially when you push beyond native language support.

In such cases, simplicity and ease-of-lookup should weigh heavily in your decision making. Adhere to the principle of least astonishment. Limit your use of exotic characters (that is, exotic outside your specific development environment) to maximize your expected rewards compared to the costs of typing and discoverability.

For globally published APIs, universal standards offer the best opportunities to integrate Swift symbology into your code. Even so, you may still prefer sum and product to ∑ and ∏ for simple, consumer convenience.

As a final amusing note, Chris Lattner has assured the integrity of at least a portion of the symbol set. On Swift Evolution, he wrote that any proposal for future Swift updates that breaks

let ?? = "moof"

will not be tolerated.

8 Comments

  • I love the idea of using special unicode for operators – the big issue now is trying to find a good font to use. I posted a question on the xcode-users list but no one had a good solution. In the end I posted a reasonable solution:


    I recently downloaded two DejaVu Sans fonts – one is a proportional font (shows up in Font Book as a “Deja Sans Book”) the other monospaced (“Deja Sans Mono Book”)

    In Xcode, select all options (CMD-A) in the Font and Colors pane, and change the Font to Deja Vu Sans Mono. Then select just the “Function and Method Names”, then select “Deja Vu Sans” for the font.

    The function and method names will be slightly “squished”, but the Unicode symbols are now nice and big.

    I also have a rdar in that Apple should provide a separate font setting for operators to facilitate this.

    If anyone has a good solution I’m all ears.

  • I find Fira Code and Hasklig (ligature fonts designed for use with Haskell) work really nicely with Swift:

    http://i.imgur.com/xQCZ36R.png

    https://github.com/tonsky/FiraCode
    https://github.com/i-tu/Hasklig

  • Another use case for unicode is demonstration code. Emojis as variable or function names may look silly and I would not use them in day-to-day life, but when you’re doing a demo,

    var ?: Int

    beats

    var creditCardNumber: Int
    hands down.

    Given the problems of making code readable on the relatively small space of a projector screen, emojis break up functions and help people to parse code they only see for short periods of time and which may not reappear for several slides.

    • I’d argue that what looks like a small rectangle with lines at first glance may involve a greater cognitive burden than the words creditCardNumber for most. It certainly took me until after your “beats” line to figure out what example you were creating. That’s because the credit card symbol as used in the Emoji set does not appear much in normal print sources. People are not trained in it.

      If it were a combination of, say, the Master Card/Visa/Discovery(does that still exist)/Amex logos, it might work better because we’re constantly exposed to those in context. It might also work in a GUI because it’s clear from a context established by a “Payment method” label, for example.

      But alone in code, I’m not sure it improves upon creditCardNumber

  • You actually don’t need a text-replacement for the  symbol. It’s just Shift-Alt-K on Mac.

    • It always takes me at least 5 minutes to work through all the key combinations for . That screenshot is my actual replacement list, not one I use for development since I tend to avoid emoji and symbols for my code since nearly everything I write is meant for external consumption.

  • ctrl-⌘-space brings up a compact character palette at the insertion point. I find it much quicker than copy/pasting from the floating Emoji & Symbols window!

    • I have control-⌘-space set up to launch the full character window. I like it better that way.