Reputation: 12670
The Swift compiler (Xcode 7.0 beta 5) crashes with "Illegal instruction: 4", "non-canonical or unchecked type" when fed this specific source line (inside a larger piece of code):
let z = y.filter() { (_, x) in x.type == .A(_) }
The elements of y
are tuples. Their first elements extend NSObject
. Their second elements have a property type
, which is an enumeration that includes A(Int)
.
Is there an (obvious) mistake in my code?
UPDATE If I attempt this work-around I run into errors "Use of unresolved identifier 'x'" in the lines that contain if
and append
respectively:
var z = []
for (_, x: X) in y {
if x.type == .A(_) {
z.append((_, x))
}
}
Again, is there an (obvious) mistake in this code?
Upvotes: 0
Views: 259
Reputation: 21259
let z = y.filter() { (_, x) in x.type == .A(_) }
If your array is array of tuples, as you wrote, closure signature is ...
(t) -> Bool
... where t
is your tuple and Bool
is return value. If true
is returned, t
is included in result otherwise it's not. You have to access elements of your tuple with t.0
and t.1
.
for (_, x: X) in y {
if x.type == .A(_) {
z.append((_, x))
}
}
It's not possible to check .type
with == .A
like you do. Also you're saying that you're not interested in first elements of your tuples (_
in for ... in
loop) and later you're trying to use first element with _
, which is not going to work as well.
Let's define some types first ...
enum MyType {
case A(Int)
case B(Float)
}
class Dummy: NSObject {}
class DummyValue {
var type: MyType
init(_ type: MyType) {
self.type = type
}
}
... and now some DummyValue
...
let dv = DummyValue(.A(1))
You're trying to check type
with ...
if dv.type == .A(_) { ... }
... which is not going to work. You can use switch
...
switch dv.type {
case .A(_): print(".A")
default: print("Other")
}
... or pattern matching with if
& case
...
if case .A(_) = dv.type {
print(".A")
}
Let's transform your for in
loop to a working form ...
let y = [
(Dummy(), DummyValue(.A(1))),
(Dummy(), DummyValue(.B(3.0))),
(Dummy(), DummyValue(.A(2)))
]
var z = [(Dummy,DummyValue)]()
for (a, b) in y {
if case .A(_) = b.type {
z.append((a,b))
}
}
print(z.count) // Output = 2
It's not nice and we don't want to have if case ...
or switch ...
in our filter
...
z = y.filter { if case .A(_) = $0.1.type { return true }; return false }
... so, we can extend MyType
with computed property isA
...
extension MyType {
var isA: Bool {
switch self {
case .A(_): return true
default: return false
}
}
}
... and transform filter
into this simple form ...
z = y.filter { $0.1.type.isA }
I can dream of nicer solution, but since there're still some limitations in pattern matching in current beta ... :-)
Upvotes: 1