brandonscript
brandonscript

Reputation: 72975

Swift 4 switch statement comparing multiple values, using greater than or less than

I know in Swift I can do a simple Swift switch statement to compare computed values with a single variable:

let distanceTravelled = -145.1
switch distanceTravelled {
case _ where distanceTravelled < 15:
    print("You travelled the right distance")
default:
    print("Sad face")
}

But I want to be able to set up a matrix of comparisons using tuples, something like this:

let distanceTravelled = -145.1,
    origin = 2

switch (origin, distanceTravelled) {
case (2, _ where distanceTravelled < 15):
    print("You travelled the right distance")
default:
    print("Sad face")
}

But this doesn't compile, complaining that expected ',' separator and expected expression in list of expressions.

Obviously this is syntactically incorrect, but shouldn't it work given that this works?

switch (2, -145.1) {
case (2, _):
    print("You travelled the right distance")
default:
    print("Sad face")
}

Upvotes: 1

Views: 2865

Answers (1)

brandonscript
brandonscript

Reputation: 72975

Aha! Found the answer in the good ol' Swift docs. I wasn't thinking of this in terms of the condition being a tuple.

switch (origin, distanceTravelled) {
case let (_, d) where d < 15:
    print("You travelled the right distance")
default:
    print("Sad face")
}

For my actual use case, this got a little weirder because I was comparing an enum property for origin, but it worked out:

let absOriginDistanceFromDefault = abs(defaultDividerPosition - viewDividerOrigin)

switch (splitViewOrigin, distanceTravelled) {
case let (.defaultPosition, d) where d < -100:
    return .shouldMoveToTopView
case let (.defaultPosition, d) where d > 100:
    return .shouldMoveToBottomView
case (.topView, _) where currentDividerPosition - defaultDividerPosition < -100:
    return .shouldMoveToBottomView
case (.topView, _) where abs(distanceTravelled) > absOriginDistanceFromDefault * 0.5 && currentDividerPosition < self.view.bounds.height:
    return .shouldMoveToDefaultPosition
case (.bottomView, _) where currentDividerPosition - defaultDividerPosition > 100:
    return .shouldMoveToTopView
case (.bottomView, _) where abs(distanceTravelled) > absOriginDistanceFromDefault * 0.3 && currentDividerPosition > 0:
    return .shouldMoveToDefaultPosition
default:
    return .shouldReturnToOrigin
}

And oddly enough, in simplifying it further, it turns out I don't even need to declare variables in the first two checks at all:

let absOriginDistanceFromDefault = abs(defaultDividerPosition - viewDividerOrigin)

switch (splitViewOrigin, distanceTravelled) {
case (.defaultPosition, _) where distanceTravelled < -100,
     (.bottomView, _) where currentDividerPosition - defaultDividerPosition > 100:
    return .shouldMoveToTopView
case (.defaultPosition, _) where distanceTravelled > 100,
     (.topView, _) where currentDividerPosition - defaultDividerPosition < -100:
    return .shouldMoveToBottomView
case (.topView, _) where abs(distanceTravelled) > absOriginDistanceFromDefault * 0.5 && currentDividerPosition < maxHeight,
     (.bottomView, _) where abs(distanceTravelled) > absOriginDistanceFromDefault * 0.3 && currentDividerPosition > 0:
    return .shouldMoveToDefaultPosition
default:
    return .shouldReturnToOrigin
}

Upvotes: 5

Related Questions