View source: R/nested_ifelse_linter.R
nested_ifelse_linter | R Documentation |
ifelse()
callsCalling ifelse()
in nested calls is problematic for two main reasons:
It can be hard to read – mapping the code to the expected output for such code can be a messy task/require a lot of mental bandwidth, especially for code that nests more than once
It is inefficient – ifelse()
can evaluate all of its arguments at
both yes and no (see https://stackoverflow.com/q/16275149); this issue
is exacerbated for nested calls
nested_ifelse_linter()
Users can instead rely on a more readable alternative modeled after SQL CASE WHEN statements.
Let's say this is our original code:
ifelse( x == "a", 2L, ifelse(x == "b", 3L, 1L) )
Here are a few ways to avoid nesting and make the code more readable:
Use data.table::fcase()
data.table::fcase( x == "a", 2L, x == "b", 3L, default = 1L )
Use dplyr::case_match()
dplyr::case_match( x, "a" ~ 2L, "b" ~ 3L, .default = 1L )
Use a look-up-and-merge approach (build a mapping table between values and outputs and merge this to the input)
default <- 1L values <- data.frame( a = 2L, b = 3L ) found_value <- values[[x]] ifelse(is.null(found_value), default, found_value)
efficiency, readability
linters for a complete list of linters available in lintr.
# will produce lints
lint(
text = 'ifelse(x == "a", 1L, ifelse(x == "b", 2L, 3L))',
linters = nested_ifelse_linter()
)
# okay
lint(
text = 'dplyr::case_when(x == "a" ~ 1L, x == "b" ~ 2L, TRUE ~ 3L)',
linters = nested_ifelse_linter()
)
lint(
text = 'data.table::fcase(x == "a", 1L, x == "b", 2L, default = 3L)',
linters = nested_ifelse_linter()
)
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.