We can increase the usability of our function by providing a generic type for the set of keys we provide as the second parameter:
func makeDuplicates<ItemType, KeyType>(of item: ItemType, withKeys keys: Set<KeyType>) -> [KeyType: ItemType] {
var duplicates = [KeyType: ItemType]()
for key in keys {
duplicates[key] = item
}
return duplicates
}
Multiple generic types are defined just as they were in the previous recipe--as a comma-separated list within the angle brackets.
All the collection types in Swift (array, dictionary, set, and so on) use generics, and in the preceding function, we are passing in the generic type from our function into the set; therefore, KeyType must have the same constraints that are imposed by the set, which means the type must conform to Hashable.
If we wanted to make this constraint explicit, or constrain the generic type for some other reason, this is defined after a colon:
func makeDuplicates<ItemType, KeyType: Hashable>(of item: ItemType, withKeys keys: Set<KeyType>) -> [KeyType: ItemType] {
var duplicates = [KeyType: ItemType]()
for key in keys {
duplicates[key] = item
}
return duplicates
}
Just as before, since we provide a parameter with specific types when using our method, the generic type is given a specific type:
let awards: Set<String> = ["Director",
"Cinematography",
"Film Editing",
"Visual Effects",
"Original Music Score",
"Sound Editing",
"Sound Mixing"]
let oscars2014 = makeDuplicates(of: "Gravity", withKeys: awards)
print(oscars2014["Director"]) // Gravity
print(oscars2014["Visual Effects"]) // Gravity