let rangeName = [0..<1.3: "Very low", 1.3..<3: "Average", 3.0..<100: "Excellent"]
But if I change it to (see last range):
let rangeName = [0..<1.3: "Very low", 1.3..<3: "Average", 3.0...100: "Excellent"]
I have this error:
error: heterogeneous collection literal could only be inferred to '[AnyHashable : String]'; add explicit type annotation if this is intentional
let rangeName = [0..<1.3: "Very low", 1.3..<3: "Average", 3.0...100: "Excellent"]
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
as [AnyHashable : String]
I don't know how to specify the type to make it compile. Is it even possible?
There is RangeExpression, but that doesn‘t require Hashable And it has an associated type, so it won‘t help much here.
I‘m not sure a dictionary is the appropriate structure here anyway.
If you want to get a string for a concrete score (or whatever your number represents), a function containing a switch would not exhibit this same issue, and would even allow more flexibility (want a case 100: return "perfect"? That would be hard to do with a dict).
If you want to categorize your score first, and then get a description later, I‘d suggest converting your score into an enum value first, and then have a property on the enum for the description (or have a dict mapping from a “score category” enum to description).
But I don't understand how can protocols with associated types can be truly useful if we cannot use them as an interface. I mean we cannot put them in a container like an array for example and use the protocol as an interface to communicate with the members of the array. So what is the purpose? We use them to apply restrictions, but we cannot use them like protocols having no associated types.
I played with protocols with associated types (PAT). And my conclusion is that we have to use generics to use them like regular protocols. We cannot use protocol composition either.
Here is an example:
protocol S {
associatedtype X
func f(_ x: X)
}
protocol T: S where X == Double {}
protocol U {}
class C<XX: T> {
var x: [XX]
init(_ x: [XX]) {
self.x = x
}
}
class D: T, U {
func f(_ x: Double) {
print(x)
}
}
func x<E: T>(_ v: E) where E: U {
v.f(13.0)
}
D().f(10)
C([D()]).x[0].f(1.0)
x(D())
In function x we cannot use protocol composition so the clause where E: U is used as an equivalent constraint.
I was expecting to be able to use protocol T like a regular protocol because its associated type X is bound to a concrete type so there is no type ambiguity. I hope this constraint will be left soon.