rdplyrquasiquotes

default arguments not being recognized in custom function using dplyr


Take this function foo(). I want it to have a default argument of cyl because that's the name of the field it will usually process.

library(tidyverse)

foo <- function(x = cyl){
    case_when(
        x == 6 ~ TRUE,
        x == 8 ~ FALSE,
        x == 4 ~ NA
    )
}

# works: 
mtcars %>% 
    mutate(cyl_refactor = foo(cyl)) %>% 
    select(cyl, cyl_refactor)

But I am surprised that the function will not work unless I explicitly supply the default argument. See failing code below

# fails:
mtcars %>% 
    mutate(cyl_refactor = foo()) %>% 
    select(cyl, cyl_refactor)

Error: Problem with `mutate()` column `cyl_refactor`. ℹ `cyl_refactor = foo()`. x object 'cyl' not found

It seems that default arguments are only processed when there is also a data parameter as below.

foo2 <- function(data, x = cyl){
    data %>% 
        mutate(cyl_refactor = case_when(
        {{x}} == 6 ~ TRUE,
        {{x}} == 8 ~ FALSE,
        {{x}} == 4 ~ NA
    ))
}

mtcars %>% 
    foo2() %>% 
    select(cyl, cyl_refactor)

I am sure there is some gap in my knowledge of quasiquotation, but I would like to understand how to use a default argument in foo().


Solution

  • We could do this with missing and cur_data_all

    foo <- function(x = cyl){
       if(missing(x)) x <- cur_data_all()[["cyl"]]
       
        case_when(
            x == 6 ~ TRUE,
            x == 8 ~ FALSE,
            x == 4 ~ NA
        )
    }
    

    -testing

    > out1 <- mtcars %>% 
    +     mutate(cyl_refactor = foo(cyl)) %>% 
    +     select(cyl, cyl_refactor)
    > out2 <- mtcars %>% 
    +     mutate(cyl_refactor = foo()) %>% 
    +     select(cyl, cyl_refactor)
    > 
    > identical(out1, out2)
    [1] TRUE