Boolean multiplicity and Swift

Late last week, I was helping a fairly new Swift developer with his code that initially looked like this:

func generateContact(withAddress: Bool, withEmail: Bool, withPhone: Bool) -> Customer // not my code

It occurred to me that multiple Boolean flags would be much better represented as ad-hoc option sets. So I set out to discover how often this pattern showed up in code. I asked for examples on the Swift Evolution list, headed over to both Github and to searchcode.com, trying to track down examples and determine whether this was a relatively common pattern in Swift.

I pulled down all the Apple code, cloned a lot of the top Swift Github repos, and performed searches (the best I could, all things considered) through gists to test whether multiple Bool arguments was a common use that could be improved.

What I found was this:

  • In both Apple and “Top Swift” repos, I found few circumstances where multiple boolean flags were used at all.
  • Two flags was the most common multiplicity. Three flags were rare. I don’t remember finding any with four or more.
  • Multiple booleans were primarily used initializers, with a few instances from graphics code for things like stroke and fill.
Examples:
convenience init?(before: Bool, during: Bool) {
convenience init?(before: Bool, during: Bool, after: Bool) {
func nested_if_merge_noret(x: Int, y: Bool, z: Bool) {
func render(fill: Bool, stroke: Bool) {
public init(hasStroke: Bool, hasFill: Bool, evenOdd: Bool = false) {
public init(x0: CGFloat, y0: CGFloat, rx: CGFloat, ry: CGFloat, angle: CGFloat, largeArcFlag: Bool, sweepFlag: Bool, x: CGFloat, y: CGFloat) {
I’m probably not going to press forward with the language enhancement I had in mind because I don’t see a compelling reality-based need for it after performing this check, but it would have been nice to be able to declare:
convenience init?(flags: @options(before, during, after)) {
and call it with
let foo = T.init(flags: [.before, .after])

2 Comments

  • This would be easily, and better, represented as a normal set of enum cases. You should only use an option set if you need the parameter to be very memory efficient, or to be raw representable for serialisation or compatibility.

    • That would work fine as well. My reasoning was this: that flags have an intrinsic “Option Set” mentality representing multiple related options, as in a composable typedef enum. Either way would work fine for me.