Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a way to make Objective-C support a multi-variable switch construct?

I was wondering: is there a way to make Objective-C support a multi-variable switch construct?

I mean, very often I have to deal with problems in which the solution depends on a pair of variables instead of a single one. For a long list of single variable values one can use a simple switch/case construct:

switch (var) {
    case 0: ...
    case 1: ...
    default: ...
}

But when you have to deal with the combination of two values you often happen to do something like this:

switch (var1) {
    case 0: 
        switch (var2) {
            case 0: ...
            case 1: ...
        }
    case 1: 
        switch (var2) {
            case 0: ...
            case 1: ...
        }        
    ...
}

And it gets more and more complicated ... What I'd really love to do is something like this:

switch (var1, var2) {
    case (0,0) : ...
    case (1,0) : ...
    case (*,1) : ...
    default: ...
}

that will result in a more simple and readable construct. Is there any solution to support such a structure? Or a slight variation of this one?

like image 787
marzapower Avatar asked Jun 08 '11 15:06

marzapower


2 Answers

I like the answer from saphrosit but I'll make try to make it easy to understand.

Imagine the possible outcomes of your problem as squares in a grid where one edge of the edge of the grid represents values of var1 and the other edge represents the possible values of var2, then if you incrementialy counted through the squares of the of the grid you would it get something like this

      ||                              var1                                   |    
      ||    0    |     1     |     2     | ... |     j     | ... |   n-1     |
======++=====================================================================|
    0 ||    0    |     1     |     2     | ... |     j     | ... |   n-1     |
   ---||---------+-----------+-----------+-----+-----------+-----+-----------|
    1 ||    n    |    n+1    |    n+2    | ... |    n+j    | ... |  n+(n-1)  |
   ---||---------+-----------+-----------+-----+-----------+-----+-----------| 
    2 ||   2*n   |   2*n+1   |  2*n+2    | ... |   2*n+j   | ... | 2*n+(n-1) |
 v ---||---------+-----------+-----------+-----+-----------+-----+-----------|
 a    ||    .    |     .     |     .     |     |     .     |     |  .        |
 r ---||---------+-----------+-----------+-----+-----------+-----+-----------|
 2  i ||   i*n   |   i*n+1   |   i*n+2   | ... |   i*n+j   | ... | i*n+(n-1) |
   ---||---------+-----------+-----------+-----+-----------+-----+-----------|
      ||    .    |      .    |      .    |     |     .     |     |  .        |
  ----||---------+-----------+-----------+-----+-----------+-----+-----------|
  m-1 || (m-1)*n | (m-1)*n+1 | (m-1)*n+2 | ... | (m-1)*n+j | ... |   mn-1    | <-- (m-1)*n+(n-1) = m*n-n + (n-1) = mn-1
------||---------+-----------+-----------+-----+-----------+-----+-----------|

This would is called a row major matrix since you start by counting accross the rows. There is also a column major matrix where you start counting down first instead of across. This is how matrixes are stored in the C BLAS library so it should be very fimilar to many people.

In your case the outcome you're looking for can be addressed as var3 = var2*n + var1 you could lay this out in code as

#define N 10 // Maximum size of var1

int main() {

   int var1 = 1;
   int var2 = 1;

   switch(var1 + var2 * N){
      case 1 + 1 * N: printf("One One"); break;
      case 2 + 2 * N: printf("Two Two"); break;
      default:
      printf("Bada Bing");
   }

   return 0;
}

NOTE: the code that was here earlier wouldn't have worked, this works.

like image 69
user160917 Avatar answered Sep 19 '22 18:09

user160917


In your question you mention: "What I'd really love to do is something like this:"

switch (var1, var2) {
    case (0,0) : ...
    case (1,0) : ...
    case (*,1) : ...
    default: ...
}

If it is the case that your possible values are in the range {0..n}, there are two methods you could use.

  1. You could construct a multidimensional array of selectors and then select the correct selector using your var1, var2. (This method is more efficient due to the constructing of the selectors at compile time)

  2. You could construct the selector name based on the values of the var,var2 variables.

BOTH methods are exemplified here in this code snippet.

- (void) case00 {
    NSLog(@"Case ZeroZero");
}

- (void) testSelectorIdea {
     NSInteger var1 = 0;
     NSInteger var2 = 0;

// ----- ARRAY OF SELECTORS METHOD ----
    SEL selectors[2][2] = {@selector(case00),@selector(case01), @selector(case10), @selector(case11)};
    [self performSelector:selectors[var1][var2]];


// ----- SELECTOR CONSTRUCTION METHOD ----
    NSString * selectorName = [NSString stringWithFormat:@"case%d%d",var1,var2];
    SEL  selector = NSSelectorFromString(selectorName);
    [self  performSelector:selector];

}
like image 23
YuzaKen Avatar answered Sep 21 '22 18:09

YuzaKen