3

In many languages, there is an instruction called break that tells the interpreter to exit the switch after the current statement. If you omit it, the switch fall-through after the current case has been processed:

switch (current_step)
{
  case 1: 
    print("Processing the first step...");
    # [...]
  case 2: 
    print("Processing the second step...");
    # [...]
  case 3: 
    print("Processing the third step...");
    # [...]
    break;
  case 4: 
    print("All steps have already been processed!");
    break;
}

Such a design pattern can be useful if you want to go through a serie of transitive conditions.


I understand that this can cause bugs due to unintentional fallthrough if the programmer forgets to insert the break statement, but several languages are breaking by default, and include a fallthrough keyword (e.g. continuein Perl).

And by design, the R switch also breaks by default at the end of each case:

switch(current_step, 
  {
    print("Processing the first step...")
  },
  {
    print("Processing the second step...")
  },
  {
    print("Processing the third step...")
  },
  {
    print("All steps have already been processed!")
  }
)

In the above code, if current_step is set to 1, the output will only be "Processing the first step...".


Is there any way in R to force a switch case to fall through the following case?

Antoine C.
  • 3,730
  • 5
  • 32
  • 56
  • https://stackoverflow.com/a/17113744/1457051 is the best you are going to be able to do. – hrbrmstr May 05 '18 at 11:17
  • @hrbrmstr it is close but still not a real fall-through, this solution only allows multiple labels for one case. – Antoine C. May 05 '18 at 12:53
  • @Lovy - If you don't like the behavior of the R `switch()` statement, you can always code your own version. – Len Greski May 05 '18 at 14:55
  • @Lovy I know. I said "the best you are able to do" for a reason. Feel free to [reimplement the primitive](https://github.com/wch/r-source/blob/3f7ba9e344d4fc3688a16006386b6a5019d89f89/src/main/builtin.c#L1026). – hrbrmstr May 05 '18 at 18:06

1 Answers1

1

It appears that such a behavior is not possible with switch(). As suggested in the comments, the best option was to implement my own version.


Thus, I pushed an update to my optional package to implement this feature (CRAN).

With this update, you can now use a fallthrough statement in the pattern-matching function match_with.

The design pattern in the question can be reproduced the following way:

library(optional)
a <- 1
match_with(a
    1, fallthrough(function() "Processing the first step..."),
    2, fallthrough(function() "Processing the second step..."),
    3, function() "Processing the third step...",
    4, function() "All steps have already been processed!"
)
## [1] "Processing the first step..." "Processing the second step..." "Processing the third step..."

You can observe that match_with() is quite similar to switch(), but it has extended capabilities. E.g. the patterns can be lists or functional sequences instead of being simple objects to compare:

library("magrittr")
b <- 4
match_with(a,
  . %>% if (. %% 2 == 0)., 
  fallthrough( function() "This number is even" ),
  . %>% if ( sqrt(.) == round(sqrt(.)) ).,  
  function() "This number is a perfect square"
)
## [1] "This number is even" "This number is a perfect square"
Antoine C.
  • 3,730
  • 5
  • 32
  • 56