0

I can't seem to find an SO post that helps me solve this problem. My minimally reproducible example is:

bigfn <- function(x) {
  smallfn(x)
}

smallfn <- function(y) {
  y <- rlang::enquo(y)
  print(y)
  print(rlang::quo_is_missing(y))
}

The output of bigfn() is:

<quosure>
expr: ^x
env:  0x7fc93fc0f8c8
[1] FALSE

But I would like the quosure to be an empty quosure and FALSE to be TRUE to reflect the fact that bigfn propagated down a missing value through smallfn.

Additionally, I don't want to just move the enquo into bigfn because I would still like to be able to use smallfn independent of bigfn.

Dylan Russell
  • 936
  • 1
  • 10
  • 29

2 Answers2

3

Perhaps a pattern called "forwarding the dots" may be useful here. It preserves missing arguments and behaves well in the context of non-standard evaluation:

bigfn <- function(...) {
  smallfn(...)
}

bigfn()
# <quosure>
# expr: ^
# env:  empty
# [1] TRUE

However, if you do need to have specific arguments referenced by name, you will need to "tunnel" them with {{ (which is shorthand for !!enquo) to smallfn():

bigfn <- function(x) {
  smallfn({{x}})
}

bigfn()
# <quosure>
# expr: ^
# env:  empty
# [1] TRUE

bigfn(42)
# <quosure>
# expr: ^42
# env:  empty
# [1] FALSE
Artem Sokolov
  • 13,196
  • 4
  • 43
  • 74
1

Why not do:

bigfn <- function(x) {
  if(missing(x)) smallfn()
  else smallfn(x)
}

Then, without changing smallfn you have:

bigfn()
#> <quosure>
#> expr: ^
#> env:  empty
#> [1] TRUE

bigfn(2)
#> <quosure>
#> expr: ^x
#> env:  00000000119E8FD0
#> [1] FALSE
Allan Cameron
  • 147,086
  • 7
  • 49
  • 87