Why does type inference not work in this switch statement in Swift 3?

UPDATE This is fixed in Swift 3.1.

When transferring the if-else to switch I noticed that type inference doesn't work. Why do I need to specify an HKQuantityTypeIdentifier in each case when quantityTypeIdentifier already of this type?

 func process(samples: [HKSample]?, quantityTypeIdentifier: HKQuantityTypeIdentifier) { DispatchQueue.main.async { [weak self] in if let quantitySamples = samples as? [HKQuantitySample] { for sample in quantitySamples { switch quantityTypeIdentifier { case HKQuantityTypeIdentifier.distanceWalkingRunning: // code case HKQuantityTypeIdentifier.activeEnergyBurned: // code case HKQuantityTypeIdentifier.heartRate: // code default: fatalError("Quantity Type Identifier not implemented \(quantityTypeIdentifier)") } } } } } 

I can call a function like:

 process(samples: samples, quantityTypeIdentifier: .distanceWalkingRunning) 
+5
source share
1 answer

I think you found a mistake, or at least you have a reasonable chance to claim it. The inconsistency is well illustrated by a much shorter example:

 let c : UIColor = .red switch c { case .red : print ("red") // error default : break } 

This does not compile. You can say .red in the first line, but not in the third line. This seems like a clear inconsistency.

Now, having said that, I can certainly explain why there are different rules in different places. The case expression is resolved in accordance with the ~= operator and the rules for generating the template. These rules are different from everything else in Swift (from here, for example, there are situations when you say as in the case template, but say as? Everywhere). So it’s obvious that these are rules that need to be set up in order for this to work. They were modified until open enumeration cases were resolved, but were not made public as β€œstructural” enumeration cases (i.e., Static members of structures that are RawRepresentable, where these static members evaluate an instance of the structure itself )

Finally, here's a hidden workaround that I like to use when case patterns get too burdensome:

 let c : UIColor = .red switch true { case c == .red : print ("red") // heh heh default : break } 

By turning on true and writing out the entire logical condition, we break the boundaries of the pattern matching and return the world of normal expressions.

+3
source

Source: https://habr.com/ru/post/1259781/


All Articles