Initializing an empty Dictionary - style question

Hi, I was reading some Wenderlich tutorials and I noticed people like to initialize Dictionaries like so:

var skipTable: [Character: Int] = [:]

But I think it's minutely easier to read:

var skipTable = [Character:Int]()

Is this just a style preference or is there a performance penalty here? Thanks.

For all intents and purposes, they're equivalent and simply a matter of style: Compiler Explorer

I will point out though that there's also the alternative

var skipTable = Dictionary<Character, Int>()

:wink:

2 Likes

i really don’t think either is superior but my personal style is to use

let dict:[T: T] = [:]

so that the type information lives on the left side of the assignment, just like any other Swift variable declaration. that’s also why i like to use

let buffer:UnsafeMutablePointer<Int> = .allocate(capacity: 13)

and

let foo:Foo = .init()
3 Likes

My reason for preferring var skipTable: [Character: Int] = [:] over the alternatives has to do with education and the order in which topics are introduced to programming students.

I am very strict about not using syntax or features a student hasn't learned yet, and not introducing things too early. As such, I teach data structures fairly early on, after control flow and functions, but before custom types. The syntax above lets me do that, as it uses a literal instead of an initializer for initialization (unlike var skipTable = [Character:Int]()) and does not require generics (unlike var skipTable = Dictionary<Character, Int>()).

3 Likes

There's no good reason for that, it's just one of those early days decisions that's hard to undo now. If to find some excuses: to distinguish which function to call:

func foo(_ x: [String : String]) {
    print("dictionary version called")
}

func foo(_ x: [String]) {
    print("array version called")
}

func foo(_ x: Set<String>) {
    print("set version called")
}

foo([:])

without putting type explicitly at the call site:

foo([] as [String: String]) // not current Swift

Interestingly foo([]) call is unambiguous here (and it feels it should be ambiguous).

With [] for empty directories and along with making comma separators optional we could have supported conditional literals like so:

// not current Swift ahead

var foo: [String: String] = [
    #if os(macOS)
    "key" : "value"   // comma is optional here
    #endif
]

var bar: [String: String] = [
    "hello" : "world" // comma is optional here
    #if os(macOS)
    "key" : "value"   // comma is optional here
    #endif
]

PS. it's better starting new threads instead of resurrecting old threads.

2 Likes