18.16 Specific use cases for recurse_call()
18.16.1 Example 1: Finding F and T
- Using
F
andT
in our code rather thanFALSE
andTRUE
is bad practice. - Say we want to walk the AST to find times when we use
F
andT
. - Start off by finding the type of
T
vsTRUE
.
- With this knowledge, we can now write the base cases of our recursive function.
- The logic is as follows:
- A constant is never a logical abberviation and a symbol is an abbreviation if it’s “F” or “T”:
logical_abbr_rec <- function(x) {
switch_expr(x,
constant = FALSE,
symbol = as_string(x) %in% c("F", "T")
)
}
- It’s best practice to write another wrapper, assuming every input you receive will be an expression.
18.16.2 Next step: code for the recursive cases
- Here we want to do the same thing for calls and for pairlists.
- Here’s the logic: recursively apply the function to each subcomponent, and return
TRUE
if any subcomponent contains a logical abbreviation. - This is simplified by using the
purrr::some()
function, which iterates over a list and returnsTRUE
if the predicate function is true for any element.
logical_abbr_rec <- function(x) {
switch_expr(x,
# Base cases
constant = FALSE,
symbol = as_string(x) %in% c("F", "T"),
# Recursive cases
call = ,
# Are we sure this is the correct function to use?
# Why not logical_abbr_rec?
pairlist = purrr::some(x, logical_abbr_rec)
)
}
logical_abbr(mean(x, na.rm = T))
#> [1] TRUE
# [1] TRUE
logical_abbr(function(x, na.rm = T) FALSE)
#> [1] TRUE
# [1] TRUE