I recently ran across this article wherein the author strongly discourages the use of emoji in HTML, CSS, and Javascript code. While I actually agree with him in that context, I want to head off the idea that any use of emoji in any language is a bad idea.
While UTF-8 is widely supported, different editors and operating systems support different levels of the Unicode standard, which can cause emoji that are readable to some viewers to appear broken to others. But in the Apple-controlled world of Xcode, where Swift development is typically done, support for the latest Unicode and emoji is very solid.
In Swift, emoji are explicitly defined in the language specification as letters and can be used anywhere letters can be used. Anywhere you can write let a = 10
you could write let πΆ = 10
. That doesnβt mean itβs a good idea but emoji have the advantage of being highly visually distinguishable, and we can use this to our advantage. Since they are letters, emoji can be used as identifiers, but never things that cannot start with or include a letter, such as numbers or operators.
After a lot of experimentation using emoji in various places, I have settled on using them in place of generic variable names (like $0
, $1
, etc.) that would otherwise be visually βbuzzyβ and for which the default name isnβt semantically very useful. This most often happens in the context of local object configuration.
For example, here is a piece of code that lazily configures a UILabel:
private lazy var myLabel: UILabel = {
let label = UILabel()
label.layer.cornerRadius = 40
label.layer.masksToBounds = true
label.backgroundColor = UIColor(white: 0, alpha: 0.5)
return label
}()
There are a couple things I would do to improve this code. The first thing is to elminate as much boilerplate as possible by using the “with-operator” (which appears as the bullet “β’” below). Note that the code below is three lines shorter and doesn’t need the trailing parentheses.
β³οΈ NOTE: I’ll have much more to say about this operator in a future post.
import WolfWith
// ...
private lazy var myLabel: UILabel = .init() β’ {
$0.layer.cornerRadius = 40
$0.layer.masksToBounds = true
$0.backgroundColor = UIColor(white: 0, alpha: 0.5)
}
This is a big improvement. Now the main thing that bothers me about it is the repeated use of $0
to represent the label being configured. Sure I could just use label in
at the start of the closure. That would add semantic meaning. But once you start using the with-operator in your code, if you want to be consistent you either have to decide to stick with $0
everywhere, or come up with a semantically-meaningful name everywhere: “label”, “view”, “button”, “gestureRecognizer,” etc. This must be kept in sync with changes to the type being configured and starts to become a cognitive burden.
The compromise I’ve struck, after trying a lot of different alternatives, is to pick a very tiny set of emoji and use them as placeholders instead of $0
, and use them in quite limited contexts. I almost always use π as it is easily recognizable and stands out visually. In Xcode I’ve created text snippets associated with triggers like $c
for π that let me type these emoji quickly.
private lazy var myLabel: UILabel = .init() β’ { (π: UILabel) in
π.layer.cornerRadius = 40
π.layer.masksToBounds = true
π.backgroundColor = UIColor(white: 0, alpha: 0.5)
}
The use of π this way creates a bold visual “through-line” in my code and quickly signals that this is object configuration. Furthermore, the use of π is entirely local to this closure and no-one who calls or uses my code ever has to use or type emoji themselves.
β³οΈ NOTE: While Swift can infer the type that π (or view
or whatever you want to name it) represents in the closure without explicitly including the type name (π: UIView)
, without it Xcode currently does a very bad job of autocompleting after the name. With it, it works fine. This has nothing to do with the use of emoji, but only the naming of the argument to the closure. So I hope this is just an oversight that will improve with time.
In the rare cases where I may want to nest configurations, I use a second emoji π, with the associated snippet $l
.
private lazy var myLabel: UILabel = .init() β’ { π in
π.layer.cornerRadius = 40
π.layer.masksToBounds = true
π.backgroundColor = UIColor(white: 0, alpha: 0.5)
π.attributedText = NSAttributedString(string: "Hello") β’ { π in
π.addAttributes = // ...
π.setAlignment = // ...
}
}
Note that if I didn’t provide my own names for the instances being configured above, I’d have one $0
in the outer closure (representing the label) and another $0
in the inner closure (representing the text.)
I have had other programmers completely freak out when they see emoji in my code. But I contend that like so many things in programming, Unicode (including emoji) is just another tool in our toolbox, and mastering a field requires learning when to use (and not use) every tool.
πΊ