Loren on the Art of MATLAB

April 28th, 2009

Switching Things Up

If you have ever used a switch statement in MATLAB and also used it in C, you might have noticed that the two constructs have different semantics.

Contents

switch in C

In C, you often terminate case statements in switch constructs with a break statement to prevent execution of the code in the case that follows. Omitting the break statement causes the code in the following case to execute. The behavior of switch statements in C is sometimes described as fall through.

switch in MATLAB

There are several major differences between switch statements in MATLAB and C.

  • MATLAB does not have fall through behavior in its switch statements and therefore no break statement is typically required for individual case statementss.
  • MATLAB case statements have another feature that C and many other languages do not have. The expression following case need not be scalar-valued, but can combine several expressions by placing the acceptable expressions in a cell array.
  • If you want to specify behavior for switch expressions that don't match any of the case expressions, use the otherwise branch. In C, use default instead.
  • Expressions for case statements can include strings and numeric expressions, not just integer values. Though you have to be careful using non-integral numbers because of round-off, this flexibility can make the intent of your code more obvious instead of seeing a list of numbers.
  • More on switch in MATLAB

    When we originally were designing switch for MATLAB, we examined much of our own C source code, and we found a huge majority of the case statements terminated in break, hence the no fall-through behavior of MATLAB. This makes the switch statement in MATLAB equivalent to an if-elseif construct. To achieve fall-through behavior in MATLAB, you can specify all the relevant expressions in one case and then conditionally compute values within that section of code.

    Do You Use switch Statements?

    I am curious to hear about your experiences using switch statements in MATLAB. Post your thoughts here.


    Get the MATLAB code

    Published with MATLAB® 7.8

    22 Responses to “Switching Things Up”

    1. Will replied on :

      I use them a lot when I’m dealing with argument, value pairs that are in varargin cell-arrays.

    2. matt fig replied on :

      I love the Matlab switch construct! When I was first learning Matlab about 5 years ago, I found myself with many of these:

      if (…)
      elseif (…)
      elseif (…)
      elseif (…)
      end

      The switch looks so much nicer in the code. This is especially true when cell arrays are used to replace multiple conditional evaluations.

    3. Yakov replied on :

      Related to differences between C and Matlab is the use of for loop. We found the following useful in some of our code:

      a=[1 2 3;4 5 6;7 8 9];
      for I=a;I,end

      It actually cycles through the columns of matrix and is an easy way to implement column-wise operations. One in a long list of undocumented behaviors.

    4. Jos replied on :

      Sometimes, I miss the fall-through C-like behavior of switch, for instance, when setting default values of input parameters to a function:

       
      function F (a,b,c,d)
      % C-style switch
      switch nargin
      case 0
         a = 1
      case 1
         b = 2
      case 2
         c = 3
      case 3
         d = 4
      end
       

      looks nicer than

       
      function F (a,b,c,d)
      % matlab-style
      if nargin < 4
         d = 1
         if nargin < 3
            c = 1
            if nargin < 2
               b = 1
               if nargin < 1
                  a = 1
               end
            end
         end
      end
       

      Just a thought

      Jos

    5. Loren replied on :

      Jos-

      You might consider inputParser for putting in default values.

      –Loren

    6. Eric replied on :

      We’ve been replacing a lot of big ugly switch statements with containers.Map since that has been added to MATLAB. Typically they are used for translating between item ‘codes’ or ‘tags’ and the corresponding long-form description or other information.

    7. Loren replied on :

      Eric-

      Out of curiosity, why change from switch to containers.Map?

      –Loren

    8. Dan Mac replied on :

      Yakov
      Thanks for that little tidbit about cycle through the columns of matrix in a for loop. I had not known about that feature. Probably would have used it often if it had.

      Dan

    9. Loren replied on :

      Yakov and Dan-

      I blogged about the for-loop behavior (and more) here.

      –Loren

    10. Eric replied on :

      Loren-
      The reason I like containers.Map for this is primarily a style thing. To me it looks neater and is easier to mentally parse/maintain when all the keys and values are respectively grouped together. Often I’m copying the keys and values from columns of a CSV or XLS file that someone else has made and it makes it really easy to copy and paste them into the M file and then wrap in {}, compared to manually breaking them out into a switch statement. It also makes it easier to do the help text for the function, because when you are done you can copy the list of keys, paste it into the help text, and then Ctrl-R to comment it.


      keys = {
      'a'
      'b'
      'c'
      'd'
      };
      values = {
      1
      2
      3
      4
      };
      map = containers.Map(keys,values);
      key = 'a';
      out = map(key)

      rather than


      key = a;
      switch key
      case 'a'
      out = 1;
      case 'b'
      out = 2;
      case 'c'
      out = 3;
      case 'd'
      out = 4'
      end

      Regards,
      Eric

    11. Joe Kirk replied on :

      I use switch statements quite frequently, and for all sorts of things.

      For example, in my “vivid” colormap [http://www.mathworks.com/matlabcentral/fileexchange/20848], I needed to interpret a string of color characters (like ‘r’ for red, ‘g’ for green, etc.) as 1×3 arrays of type double. To do this I wrote the following code:

       
      clr_mat = zeros(num_clrs,3);
      c = 0;
      for k = 1:num_clrs
          c = c + 1;
          switch lower(input(k))
              case 'r', clr_mat(c,:) = [1 0 0];  % red
              case 'g', clr_mat(c,:) = [0 1 0];  % green
              case 'b', clr_mat(c,:) = [0 0 1];  % blue
              case 'y', clr_mat(c,:) = [1 1 0];  % yellow
              case 'c', clr_mat(c,:) = [0 1 1];  % cyan
              case 'm', clr_mat(c,:) = [1 0 1];  % magenta
              case 'p', clr_mat(c,:) = [1 0 .5]; % pink
              case 'o', clr_mat(c,:) = [1 .5 0]; % orange
              case 'l', clr_mat(c,:) = [.5 1 0]; % lime green
              case 'a', clr_mat(c,:) = [0 1 .5]; % aquamarine
              case 's', clr_mat(c,:) = [0 .5 1]; % sky blue
              case 'v', clr_mat(c,:) = [.5 0 1]; % violet
              case {'k','w'}, clr_mat(c,:) = [.5 .5 .5]; % grayscale
              otherwise, c = c - 1;
          end
      end
      clr_mat = clr_mat(1:c,:);
       
    12. Joe Kirk replied on :

      By the way, in my example, colors can be repeated if desired, and by using the counter “c”, I was able to ignore invalid inputs.

    13. Kieran replied on :

      I sometimes use switch statements in the following (somewhat kludgy) manner:

      switch sprintf('%d %d', logical_test1, logical_test2)
        case '0 0'
        % Do A
        case '0 1'
        % Do B
        case '1 0'
        % Do C
        case '1 1'
        % Do D
      end
      

      This avoid a bunch of nested if statements and is somewhat clearer in my mind than:

      if logical_test1
         if logical_test2
           % Do D
         else
           % Do C
         end
      else
         if logical_test2
          % Do B
         else
          % Do A
         end
      end
      

      I’m open to suggestion to improve this.

    14. Loren replied on :

      Kieran-

      You could switch on the combined tests by converting them to “binary”:

      logtest = logtest1*2+logtest1

      switch logtest
         case 0
         case 1
         case 2
         case 3
      end
      

      I don’t know if that’s more readable or less so.

      –Loren

    15. Iain replied on :

      I have been using Malab for six years and had no idea it had a switch statement. I have always used elseif, which is a more flexible alternative. I think I will probably stick with elseif in a lot of cases.

      In the simplest cases, like Eric, I often replace long switch statements with lookup tables. I didn’t know that Matlab finally ships with a decent map data structure. The old-style way of doing Joe Kirk’s example would be to put the colors in a structure:
      color_table.r = [1 0 0]; % red
      color_table.g = [0 1 0]; % green
      ...
      and then lookup like this:
      clr_mat(c,:) = color_table.(lower(input(k)));One would have to test for field existence or catch exceptions if unknown colors might be requested.

      Of course, which approach to use is a stylistic choice and will depend on the precise situation. The book “Code Complete” has a section on “Using decision tables to replace complicated logic” that is worth considering.

    16. Cris Luengo replied on :

      Rather than Joe, Iain or Eric’s way of doing look-up tables, I like the clarity of cell arrays and the strcmp function:

      color_table = {
      'red',   [1 0 0]
      'green', [0 1 0]
      'blue',  [0 0 1]
      };
      ii = find(strcmp(color_table(:,1), name ));
      clr_mat(c,:) = color_table{ii,2};
      

      .

      The problem with containers.Map, in my opinion, is that the key and the value are physically separated. If you want to add one value to the table, you need to edit your function in two places.

      The switch statement really shines when you need to execute different bits of code based on an input, it’s not so useful for a simple table lookup.

    17. Joe Kirk replied on :

      Chris,

      I like your method for some applications.

      In the particular case I showed however, I am doing more than a simple table lookup. Instead, I am trying to take an input string of color characters and build an Mx3 matrix of RGB triplets.

      For example, if someone provides the input ‘rygb’, I want to build the matrix [1 0 0; 1 1 0; 0 1 0; 0 0 1].

      The colors need to be in the correct order, and if someone provides an invalid color character, I want to ignore it.

      To achieve this with your method, I need to do the following:

      color_table = {
          'r',    [1 0 0]     % red
          'g',    [0 1 0]     % green
          'b',    [0 0 1]     % blue
          'y',    [1 1 0]     % yellow
          'c',    [0 1 1]     % cyan
          'm',    [1 0 1]     % magenta
          'p',    [1 0 .5]    % pink
          'o',    [1 .5 0]    % orange
          'l',    [.5 1 0]    % lime green
          'a',    [0 1 .5]    % aquamarine
          's',    [0 .5 1]    % sky blue
          'v',    [.5 0 1]    % violet
          'k',    [.5 .5 .5]  % grayscale
          'w',    [.5 .5 .5]  % grayscale
          };
      
      num_clrs = length(input(:));
      clr_mat = zeros(num_clrs,3);
      c = 0;
      for k = 1:num_clrs
          c = c + 1;
          ii = find(strcmp(color_table(:,1),lower(input(k))));
          if ~isempty(ii)
              clr_mat(c,:) = color_table{ii,2};
          else
              c = c - 1;
          end
      end
      clr_mat = clr_mat(1:c,:);
      if ~isempty(clr_mat)
          clrs = clr_mat
      end
      

      In my opinion, my SWITCH statement is more compact and readable. I may use your method for other things though… :o)

    18. Jim Weiner replied on :

      A not very clearly documented feature of the switch/case construct that I’ve found useful is that it’s much more general than the examples might lead you to believe. All the examples I’ve seen have been of the form:

      switch x
      case v1

      case v2


      end

      where x is a variable or expression, and each of the vi are numeric or string constants or cells arrays comprised thereof.

      But this also works:

      switch true
      case exp1

      case exp2


      end

      where each of the expi are logical expressions. The first that evaluates as true has its branch executed.

    19. locolab replied on :

      Can you use conditional statments in a switch statment for example:

      switch num
      case num<-2
      disp(‘Num less than -2′)
      otherwise
      disp(‘Error’)
      end

    20. Loren replied on :

      locolab-

      yes, you can use conditional statements for cases in a switch statement.

      –Loren

    21. OysterEngineer replied on :

      I like the switch syntax since the code is so easy for most people to read.

      However, I don’t like how it “artificially” drives the McCabe Clclomatic complexity index high. Thus, when I document a function that I’ve written, & include the output from Code Metrics, I have to write some text to discuss why, for example, the complexity index is 14 rather than my target of less than 10.

      In many cases, my co-workers & I look at the function in detail & decide that it is clearer to use the switch-case syntax & accept the higher index rather than dividing the function into sub-functions just to get the index below 10.

      I’m under the impression that using if-ifelse syntax will result in the same complexity index as the switch-case syntax. Yet, the switch-case syntax is usually clear.

      Maybe I need to invent an Oyster Complexity Index that excludes the effect of the switch-case syntax.

      I appreciate Iain’s discussion of decision tables from Code Complete. I browsed thru our copy & see how to implement such a thing in readable code.

    22. Loren replied on :

      OysterEngineer-

      if-else will result in the same complexity as switch. We often make the same trade-off you do, to keep a switch statement instead of having some very small subfunctions. There is a reason switch drives up the complexity though. The number of possible paths through the code does indeed go up, just as in an if-else situation.

      –Loren


    MathWorks
    Loren Shure works on design of the MATLAB language at MathWorks. She writes here about once a week on MATLAB programming and related topics.

    These postings are the author's and don't necessarily represent the opinions of MathWorks.