0

I am still trying to understand quosures in R, but I do not understand why the substitution in the function below fails.

my.toggle <- function(toggle) {
  if (toggle) {
    print("yes")
  } else {
    print("no")
  }
}

fn.args <- list(toggle = T)
my.toggle(rlang::UQS(fn.args))  # fails
# Error in if (toggle) { : argument is not interpretable as logical

rlang::quo(my.toggle(rlang::UQS(fn.args)))  # but this is the right function call
# <quosure: global>
# ~my.toggle(toggle = TRUE)

It seems like calling my.toggle(rlang::UQS(fn.args)) should be equivalent to my.toggle(toggle = T) (and, indeed, that's what you get when you wrap the function call in quo), but the function does not execute correctly. What am I doing wrong?

Jake Fisher
  • 3,220
  • 3
  • 26
  • 39

1 Answers1

0

You'd have to evaluate your quosure, like so:

library(rlang)

eval_tidy(quo(my.toggle(UQS(fn.args))))

[1] "yes"
[1] "yes"

(Why does it print twice? This is an artefact of print(): print normally returns its argument, invisibly. It seems evaluating implicitly toggles visibility, so the return value prints again. If you just replace print("yes") with (print("yes")) (toggling visibility manually with parens), the behavior is consistent again with my.toggle(toggle = TRUE)). I wouldn't worry about it too much).

As to why you get the error: UQS() returns a list, specifically: a Dotted pair list of 1: $ toggle: logi TRUE. You could hack around with my.toggle(UQS(fn.args)[["toggle"]]).

Aurèle
  • 12,545
  • 1
  • 31
  • 49