swift switch statement cases have different and shared things to do
Asked Answered
O

3

6

i have code like this

switch thing {
  case thisThing:
     do thing #1
     do thing #2
  case thatThing:
     do thing #2
     do thing #3
  case anotherThing:
     do thing #4
  default:
     default
}

So, EVERY case has something that ONLY IT does. Some cases also do the same things as one or more other cases.

Is there a way to accomplish this if I don't want any repetitive code?

OR, is there a much more efficient way of doing this without switch statements at all?? I mean, I could, for example, use if statements, but like switch statements, I can't think of a way to accomplish what I want without using repetitive code.

also, this example might be more clear than the above

myFavoriteNumbers = []
myLeastFavoriteNumbers = []

switch myNumber {
case 1:
  print("my number is number 1") // do this only for case 1
  myFavoriteNumbers += [1] // do this for case 1 and case 2
case 2:
  print("this is number 2") // do this only for case 2
  myFavoriteNumbers += [2] // do this for case 1 and case 2
case 3:
  print("I don't like number 3") // do this only for case 3
  myLeastFavoriteNumbers += [3] // do this for case 3 and case 4
case 4:
  print("Number Four") // do this only for case 4
  myLeastFavoriteNumbers += [4] // do this for case 3 and case 4
default:
  print("Default")
}
Owing answered 3/8, 2016 at 19:6 Comment(4)
You can force to fallthrough from case 1 to case 2, and so on. But If you do that case 4 will execute also case 1 if it fall through all of the previous casesLoftis
https://mcmap.net/q/845631/-how-to-create-a-hex-color-string-uicolor-initializer-in-swift-duplicateLoftis
I think there's no saving to be had unless the things you want to do are complicated enough to deserve their own functions, not for things that are one line long.Intrauterine
Why not just put thing #1-5 in functions?Undercast
I
4

You can use an initial separate pattern matching statement (comparable to a single case independent from the switch statement) that covers the actions that are unique for any (valid) number, and let the switch statement follow with cases that handle actions that are common for several numbers. With this you separate the unique and common logic action, where the latter is simply implemented as usual cases for any pattern matching switch implementation.

E.g., for your example

var myFavoriteNumbers: [Int] = []
var myLeastFavoriteNumbers: [Int] = []
let myNumberDescriptions = ["my number is number 1",
    "this is number 2", "I don't like number 3", "Number Four"]

let myNumber = 1

/* unique action:
    perform a unique action (given a valid number)
    and thereafter proceed to common cases */
if 1...myNumberDescriptions.count ~= myNumber {
    print(myNumberDescriptions[myNumber-1])
}

/* common cases */
switch myNumber {

/* common case: is a favourite number */
case 1...2: myFavoriteNumbers += [myNumber]

/* common case: is a least favourite number */
case 3...4: myLeastFavoriteNumbers += [myNumber]

default:
    print("Default")
}

In case the action that is unique to any number is more complex, use the same approach as above, but use more advanced logic (e.g. an event handler) for the unique action "case".

Iodometry answered 3/8, 2016 at 20:28 Comment(5)
@Hamish thanks again, what you noted is stated quite outright in the lang. ref.: "The fallthrough keyword does not check the case conditions for the switch case that it causes execution to fall into. The fallthrough keyword simply causes code execution to move directly to the statements inside the next case ...". Updated with another (this time, valid :) alternative.Iodometry
No problem, I made the same mistake myself when first using fallthrough :) Your updated solution certainly looks like the next best alternative. I have deleted my first comment as it's no longer relevant.Rowen
@Rowen yeah, tbh I don't quite see the use of allowing fallthrough to just the next case without satisfying a pattern match (except to mimic C), but I guess I just haven't stumbled upon situations where this could be useful (yet) :)Iodometry
I completely agree – the practical usage of fallthrough is pretty limited, and it would great to have a language feature that allowed a switch to continue pattern matching after matching against a given initial case. Although the removal of fallthrough was discussed on the swift evolution mailing list and there were some fairly interesting arguments/examples for keeping it in.Rowen
@Rowen thanks for the link, that's interesting. I guess that Duff-similar device argument is once valid enough to keep fallthrough, but indeed, would be nice if, say, continue could be used in switch statements to simply move on to the next case.Iodometry
C
2

You could nest switch statements that switch on the same value, like this:

switch myNumber {
case 1...2:
    myFavoriteNumbers += [myNumber] // do this for case 1 and case 2
    switch myNumber {
    case 1:
        print("my number is number 1") // do this only for case 1
    default:
        print("this is number 2") // do this only for case 2
    }
case 3...4:
    myLeastFavoriteNumbers += [myNumber] // do this for case 3 and case 4
    switch myNumber {
    case 3:
        print("I don't like number 3") // do this only for case 3
    default:
        print("Number Four") // do this only for case 4
    }
default:
    print("Default")
}

Not the most elegant bit of code you'll ever see, but it achieves what you want to achieve without the repetition.

Cawley answered 3/8, 2016 at 20:10 Comment(0)
T
1

Fallthrough comes to mind as an obvious solution, but as somebody here already said it does not work in a way that would be helpful.

I don't have any silver bullet for you but I think I would go about this in such a way:

create one switch statement which only covers separate logic

create a second switch statement which combines common logic

switch thing {
case thisThing:
   do thing #1
case thatThing:
   do thing #4
case anotherThing:
   do thing #5
default: ()
}

switch thing {
case thisThing, thatThing:
   do thing #2
default: ()
}

It would work when your logic does not depend on the order of function calls (which it should not, if it does it may be a sign to improve your code design). To me it looks clean, however it's still not ideal..

Tapp answered 3/8, 2016 at 20:54 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.