Provide Python-style "for-else" that works as
follows: for each element, execute "for" block, if there is break
while executing "for" block, then just stop and ignore the "else"
statement, otherwise run "else" block.
Value
If any FUN returns anything other than NULL,
then the function returns the first none NULL object. If
all x fed to FUN return NULL, then this
function returns ALT_FUN (if ALT_FUN is not a function)
or the result of ALT_FUN().
Examples
# --------------------------- Basic Usage ------------------------------
# 1. ALT_FUN get executed because FUN returns NULL for all items in x
forelse(
1:10,
function(x){
cat('The input is ', x, end = '\n')
if( x > 10) return(x) else return(NULL)
},
function(){
cat('ALT_FUN is executed!\n')
'wow'
}
)
#> The input is 1
#> The input is 2
#> The input is 3
#> The input is 4
#> The input is 5
#> The input is 6
#> The input is 7
#> The input is 8
#> The input is 9
#> The input is 10
#> ALT_FUN is executed!
#> [1] "wow"
# 2. FUN returns non-NULL object
forelse(
1:10,
function(x){
cat('The input is ', x, end = '\n')
if( x %% 2 == 0 ) return(x) else return(NULL)
},
'wow'
)
#> The input is 1
#> The input is 2
#> [1] 2
# --------------------------- Performance ------------------------------
FUN <- function(x){
Sys.sleep(0.01)
if( x %% 2 == 0 ) return(x) else return(NULL)
}
microbenchmark::microbenchmark({
forelse(1:10, FUN, 'wow')
}, {
y <- unlist(lapply(1:10, FUN))
if(length(y)){
y <- y[[1]]
}else{
y <- 'wow'
}
}, {
y <- NULL
for(x in 1:10){ y <- FUN(x) }
if(is.null(y)){ y <- 'wow' }
}, times = 3)
#> Unit: milliseconds
#> expr
#> { forelse(1:10, FUN, "wow") }
#> { y <- unlist(lapply(1:10, FUN)) if (length(y)) { y <- y[[1]] } else { y <- "wow" } }
#> { y <- NULL for (x in 1:10) { y <- FUN(x) } if (is.null(y)) { y <- "wow" } }
#> min lq mean median uq max neval
#> 20.16643 20.19583 20.21771 20.22522 20.24335 20.26148 3
#> 101.00406 101.01575 101.06052 101.02744 101.08875 101.15006 3
#> 100.83222 100.89676 100.94509 100.96129 101.00153 101.04177 3