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. continue
in 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?
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"