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.18608 20.18829 20.21116 20.19049 20.2237 20.25691 3
#> 100.77877 100.92416 100.97404 101.06956 101.0717 101.07380 3
#> 100.72468 100.89876 100.95890 101.07283 101.0760 101.07918 3