% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/nested_ifelse_linter.R
\name{nested_ifelse_linter}
\alias{nested_ifelse_linter}
\title{Block usage of nested \code{ifelse()} calls}
\usage{
nested_ifelse_linter()
}
\description{
Calling \code{\link[=ifelse]{ifelse()}} in nested calls is problematic for two main reasons:
\enumerate{
\item 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
\item It is inefficient -- \code{ifelse()} can evaluate \emph{all} of its arguments at
both yes and no (see \url{https://stackoverflow.com/q/16275149}); this issue
is exacerbated for nested calls
}
}
\details{
Users can instead rely on a more readable alternative modeled after SQL
CASE WHEN statements.

Let's say this is our original code:

\if{html}{\out{<div class="sourceCode r">}}\preformatted{ifelse(
  x == "a",
  2L,
  ifelse(x == "b", 3L, 1L)
)
}\if{html}{\out{</div>}}

Here are a few ways to avoid nesting and make the code more readable:
\itemize{
\item Use \code{data.table::fcase()}

\if{html}{\out{<div class="sourceCode r">}}\preformatted{data.table::fcase(
  x == "a", 2L,
  x == "b", 3L,
  default = 1L
)
}\if{html}{\out{</div>}}
\item Use \code{dplyr::case_match()}

\if{html}{\out{<div class="sourceCode r">}}\preformatted{dplyr::case_match(
  x,
  "a" ~ 2L,
  "b" ~ 3L,
  .default = 1L
)
}\if{html}{\out{</div>}}
\item Use a look-up-and-merge approach (build a mapping table between values
and outputs and merge this to the input)

\if{html}{\out{<div class="sourceCode r">}}\preformatted{default <- 1L
values <- data.frame(
  a = 2L,
  b = 3L
)
found_value <- values[[x]]
ifelse(is.null(found_value), default, found_value)
}\if{html}{\out{</div>}}
}
}
\examples{
# 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()
)

}
\seealso{
\link{linters} for a complete list of linters available in lintr.
}
\section{Tags}{
\link[=efficiency_linters]{efficiency}, \link[=readability_linters]{readability}
}
