Two some distinct issues, but also sort of related to each other...
Consider the following:
let permittedSpeeds = 1 ... 200
let speeds = [0, 200, 100, 300]
for speed in speeds {
print("Speed \(speed): ", terminator: "")
if permittedSpeeds ~= speed {
print("permitted")
}
else {
print("not permitted")
}
}
Using the ~= operator is a more readable (as someone recently said in another thread) replacement for "contains":
if permittedSpeeds.contains(speed)
No question about that. Since Set has a contains method I tried the following:
let vowels = Set<Character>(["a", "e", "i", "o", "u"])
let letterY = Set<Character>(["y"])
let letters = Array<Character>(["a", "b", "c", "d", "e", "x", "y", "z"])
for letter in letters {
print("Letter \(letter) is a ", terminator: "")
if vowels ~= letter {
print("vowel")
}
else {
print("consonant")
}
}
This does not compile. Looks like set does not have an ~= operator that invokes the contains method. But its easy enough to create:
extension Set {
public static func ~= (pattern: Set<Element>, value: Element) -> Bool {
return pattern.contains(value)
}
}
Question 1: Is there any particular reason why this ~= operator is not in the Swift standard library?
Before doing the above I did it the following way:
public func ~= <Element: Any> (pattern: Set<Element>, value: Element) -> Bool {
return pattern.contains(value)
}
Both methods (!!) work. In fact, both can be present in the same source file, but the Set extension is always (??) invoked in that case.
Is there any reason to prefer one over the other?
Are they in fact "the same", or do they only look the same for the few cases I've tested?
Finally, to my mind the following is actually more readable:
if letter ~= vowels { ... }
I think of it as being similar to the following SQL:
where letter in ('a','e','i','o','u')
So I added this as well (inside the Set extension):
public static func ~= (value: Element, pattern: Set<Element>) -> Bool {
return pattern.contains(value)
}
Now I can put the value that I want to check if its in the set on the left and the set itself on the right.
I believe the version with pattern, value (rather than value, pattern) is necessary in order to use a switch statement:
for letter in letters {
print("Letter \(letter) is a ", terminator: "")
switch letter {
case vowels:
print("vowel")
case letterY:
print("Y")
default:
print("consonant")
}
}
This rather surprised me. But in any case, it seems to me that it would be useful to have both in the standard library (both for Set and also RangeExpression).
extension RangeExpression {
public static func ~= (value: Bound, pattern: Self) -> Bool {
return pattern.contains(value)
}
}
Am I missing something? Were these just missed or deemed not important?