Swift-style-guide: Inconsistency in initializing empty arrays and dictionaries

Created on 7 Apr 2017  ·  4Comments  ·  Source: raywenderlich/swift-style-guide

I would have to say, I agree with most of what is stated in the guidelines, but this one seems inconsistent:

https://github.com/raywenderlich/swift-style-guide#type-annotation-for-empty-arrays-and-dictionaries

The guide indicates:

// preferred
var names: [String] = []
var lookup: [String: Int] = [:]

is preferred over

// not preferred
var names = [String]()
var lookup = [String: Int]()

But the guide usually prefers inferred types in the interest of compact code:

// preferred
let message = "Click the button"
let currentBounds = computeViewBounds()

```swift
// not preferred
let message: String = "Click the button"
let currentBounds: CGRect = computeViewBounds()

If we were being consistent, shouldn't we always prefer inferred types over explicit declaration?  I would think this is more consistent
```swift
// should be preferred
var names = [String]();
var lookup = [String: Int]();

Most helpful comment

In my opinion, the guide is correct here. It simply says, when required, specify type. When not, drop it.

Ok, but isn't this really a choice of style? No, not really. Let's have a look at some examples:

// preferred
var colors: [UIColor]?
var colors: [UIColor] = []
var colors: [UIColor] = [.red, .green, .blue]

Now, let's convert those 3 examples into your suggested preference.

var colors: [UIColor]?
var colors = [UIColor]()
var colors = [UIColor.red, UIColor.green, UIColor.blue]

See what happened there? For the last row, we now need to repeat UIColor for every element in the array. You may also argue that the declarations are now less consistent with each other.

What about a method then? Well, you could of course choose to always specify type for the sake of being consistent. However, I would imagine that most developers would want to do away with redundant code.

// do we need to specify type?
var colors: [UIColor] = rainbowColors()
// no we don't
var colors = rainbowColors()

Does that make sense?

_Edit: In all fairness, you could also infer an array like this but given we are talking consistency, I am considering this one off the table. Just thought I'd be correct._

// preferred
var colors: [UIColor] = [.red, .green, .blue]
// not preferred
var colors = [.red, UIColor.green, .blue]

All 4 comments

In my opinion, the guide is correct here. It simply says, when required, specify type. When not, drop it.

Ok, but isn't this really a choice of style? No, not really. Let's have a look at some examples:

// preferred
var colors: [UIColor]?
var colors: [UIColor] = []
var colors: [UIColor] = [.red, .green, .blue]

Now, let's convert those 3 examples into your suggested preference.

var colors: [UIColor]?
var colors = [UIColor]()
var colors = [UIColor.red, UIColor.green, UIColor.blue]

See what happened there? For the last row, we now need to repeat UIColor for every element in the array. You may also argue that the declarations are now less consistent with each other.

What about a method then? Well, you could of course choose to always specify type for the sake of being consistent. However, I would imagine that most developers would want to do away with redundant code.

// do we need to specify type?
var colors: [UIColor] = rainbowColors()
// no we don't
var colors = rainbowColors()

Does that make sense?

_Edit: In all fairness, you could also infer an array like this but given we are talking consistency, I am considering this one off the table. Just thought I'd be correct._

// preferred
var colors: [UIColor] = [.red, .green, .blue]
// not preferred
var colors = [.red, UIColor.green, .blue]

I would have gone with

var colors: [UIColor]?
var colors = [UIColor]()
var colors: [UIColor] = [.red, .green, .blue]

Instead of what you did above. Are we not preferring to use inferred type except when explicit declaration is required? In that sense the third line seems consistent.

You are right in the sense that I probably over simplified the rule. Having that said, there's nothing wrong with either approaches, it just comes down to preference. In my case, I find the below more consistent, more readable and more practical when going back and forth empty / non-empty states. I think we should let others chime in.

// preferred
var colors: [UIColor]?
var colors: [UIColor] = []
var colors: [UIColor] = [.red]
// not preferred (in my opinion)
var colors: [UIColor]?
var colors = [UIColor]()
var colors: [UIColor] = [.red]

The problem you have with that is this inconsistency:

// inconsistent?
var colors: [UIColor] = []
var colors = rainbowColors()
// your preference
var colors = [UIColor]()
var colors = rainbowColors()

@RobertGummesson, you're only taking the types that are most used with array/dictionary literal syntax into consideration. If we only had arrays to populate with array literals, both solutions would be fine. I even used to use what you were suggesting. But then we got sets, and I had to standardize on a convention that included them too. The one you're suggesting is uglier than explicit typing.

var ints: Set = [1, 1, 2, 2]
var ints = Set([1, 1, 2, 2])
var ints = Set(arrayLiteral: 1, 1, 2, 2)

So, after settling on the top choice being better for non-empty sets, an empty version, and array conventions to match, can be backformed.

var ints: Set<Int> = []
var ints = Set<Int>() // instead of this, which, without the above, seems fine.

var ints = [1, 1, 2, 2]
var ints: [Int] = []
Was this page helpful?
0 / 5 - 0 ratings

Related issues

samkim102 picture samkim102  ·  6Comments

aramezk picture aramezk  ·  9Comments

gokselkoksal picture gokselkoksal  ·  9Comments

Lweek picture Lweek  ·  5Comments

xezun picture xezun  ·  6Comments