Reputation: 390
I wanted to create an Array extension that transforms an array into a Dictionary with generic Key/Value types.
This is my code:
extension Array {
func transformToDictionary<K: Hashable, V>(@noescape mappingFunction: (Array.Generator.Element) -> (K, V)) -> [K: V] {
var dict: [K: V] = [:]
for el in self {
let result = mappingFunction(el)
dict[result.0] = result.1
}
return dict
}
}
This works for some cases like:
let stringArray = ["String1", "String2"]
stringArray.transformToDictionary({ (element: String) -> (Int, String) in
return (element.hashValue, element)
})
But doesn't work in another case like:
let nestedStringArray = [["String1"], ["String2"]]
stringArray.transformToDictionary({ (element: [String]) -> (Int, String) in
return (element.first!.hashValue, element.first!)
})
This will lead to a compiler error saying:
Can't invoke 'transformToDictionary' with an argument list of type (([String) -> (Int, String))
Did I do anything wrong here or is this a Swift compiler bug?
Upvotes: 3
Views: 2623
Reputation: 1926
In your second case you're trying to perform the nested array operation on the stringArray object. Change stringArray to nestedStringArray here and it should work (at least it did in my Playground):
let nestedStringArray = [["String1"], ["String2"]]
nestedStringArray.transformToDictionary({ (element: [String]) -> (Int, String) in
return (element.first!.hashValue, element.first!)
})
Upvotes: 1
Reputation: 9002
First let's inspect the first example:
let stringArray = ["String1", "String2"]
stringArray.transformToDictionary({ (element: String) -> (Int, String) in
return (element.hashValue, element)
})
stringArray
is an Array
of String
objects and the transformToDictionary
method expects a String
(element
) and returns a tuple of Int
and String
. This works as you have pointed out.
Now take the second example:
let nestedStringArray = [["String1"], ["String2"]]
stringArray.transformToDictionary({ (element: [String]) -> (Int, String) in
return (element.first!.hashValue, element.first!)
})
The nestedStringArray
is not used and the transformToDictionary
method is actually being called on stringArray
.
If we fix that:
let nestedStringArray = [["String1"], ["String2"]]
nestedStringArray.transformToDictionary({ (element: [String]) -> (Int, String) in
return (element.first!.hashValue, element.first!)
})
We will still get the error you mentioned:
Cannot invoke 'transformToDictionary' with an argument list of type '(([String]) -> (Int, String))'
The reason for this is that the 2nd item in the returned tuple is a String
, but the input value is a string array ([String]
).
This usage will work with an array of strings:
let nestedStringArray = [["String1"], ["String2"]]
nestedStringArray.transformToDictionary({ (element: [String]) -> (Int, [String]) in
return (0, element)
})
Upvotes: 0