如何在使用enquo()的函数上使用purr::invoke_map()?

如何在使用enquo()的函数上使用purr::invoke_map()?,r,lazy-evaluation,tidyverse,purrr,rlang,R,Lazy Evaluation,Tidyverse,Purrr,Rlang,对不起,我知道标题不是最好的 因此,我试图编写一个函数来检查两个函数的输出是否相同。我正试图用purrr::invoke\u map()实现这一点。然而,我正在努力使它与任何使用enquo()的函数一起工作 我假设问题是因为参数在我希望它们被评估之前就被评估了 library(tidyverse) check_output <- function(function_list, param_list = NULL){ param_list <- list(param_list)

对不起,我知道标题不是最好的

因此,我试图编写一个函数来检查两个函数的输出是否相同。我正试图用
purrr::invoke\u map()
实现这一点。然而,我正在努力使它与任何使用
enquo()
的函数一起工作

我假设问题是因为参数在我希望它们被评估之前就被评估了

library(tidyverse)

check_output <- function(function_list, param_list = NULL){
  param_list <- list(param_list) 
  output <- invoke_map(.f = function_list, .x = param_list) 
  identical(output[1], output[2])
}

check_output(function_list = list(cumprod, cumsum),  # This works
             param_list = list(x = iris$Sepal.Length))

check_output(function_list = list(cumsum, cumsum), # This works
             param_list = list(x = iris$Sepal.Length))

m <- function(data, col_name){ # Enquo test function
  col_name <- enquo(col_name)
 data %>% 
    select(!!col_name)
}
n <- m

n(iris, Species) # Seeing if the functions work

check_output(function_list = list(m, n),     # The call doesn't work
             param_list = list(data = iris, col_name = Species))
库(tidyverse)

check_output我通过添加一个名为add_quo的助手函数解决了问题,该函数将适当的参数转换为quosures

require(purrr)
require(magrittr) 
require(rlang) # add_quo uses this package

add_quo <- function(...) {
  ## Formats arguments for use in invoke_map()

  # Create a logical vector for use as an index below
  index <- exprs(...) %>%                       # Captures the arguments
    unlist() %>%                                # Makes them mappable
    map_if(negate(is.name), 
           .f = function(x) {return(TRUE)}) %>% # Replaces unnecessary args with TRUE
    map_if(is.name, as_character) %>%           # Converts named arguments to characters
    map_if(is.character, exists) %>%            # Replaces named args that aren't objects as FALSE
    unlist()                                    # To make index mappable

  # Wraps named args that aren't objects in new_quosure()
  exprs(...) %>%                    # Captures arguments
    unlist() %>%                    # Makes them mappable
    map_if(!index, new_quosure,     # Wraps non-object named arg in new_quosure()
           env = global_env()) %>%  # new_quosure() used instead of quo() as env must be global
    map_if(index, eval) %>%         # Removes expr() formatting
    list()                          # Makes arguments usable in invoke_map()
}

is.output.same<- function(.f_list, ...) {
  ## Checks to see if functions produce identical output

  param_list <- add_quo(...) # Enables function with dplyr syntax to work
  invoke_map(.f = .f_list, .x = param_list) %>%  # Pass args to functions
    reduce(identical) # Sees if all outputs are identical
}

check_output(function_list = list(m, n), data = iris, col_name = Species) #now works
require(purrr)
需要(magrittr)
需要(rlang)#添加#使用此软件包
添加“%”使其可映射
map_if(否定(is.name),
.f=函数(x){return(TRUE)})%>%#用TRUE替换不必要的参数
map_if(is.name,as_character)%>%#将命名参数转换为字符
map_if(is.character,exists)%>%#将非对象的命名参数替换为FALSE
unlist()#使索引可映射
#包装在new_quosure()中不是对象的命名参数
exprs(…)%>%#捕获参数
unlist()%>%#使它们可映射
映射如果(!index,new#quosure,#在new#quosure()中包装名为arg的非对象
env=global_env())%>%#使用new_quosure()代替quo(),因为env必须是全局的
map_if(index,eval)%>%#删除expr()格式
list()#使参数在invoke_map()中可用
}

is.output.samequaling输入会禁止求值,并且似乎得到了正确的解析:
检查输出(function\u list=list(m,n),param\u list=list(data=iris,col\u name=quo(Species))
是否有方法在函数调用中不使用
quo()
包装物种?还有其他类型的引用,但问题是,当
check_output
调用
list(param_list)
时,会对参数求值(太早)。报价是避免评估的最直接方式。您可以在
enquo
检查\u输出,但如果它还应该处理数字向量之类的问题,那么可能会导致问题。现在就玩吧。有没有办法在不使用
quo()
的情况下,将
param_list
作为单独的参数而不是参数列表来执行此操作?如果它最终被传递到
invoke_map
,如果在
检查输出
中使用
..
,并将其传递到
调用映射的
..
参数,而不是使用
.x
(如果可以避免的话),则可能会起作用。
.x
的问题在于它只需要一个列表,而传递列表中未赋值内容的唯一方法是以某种形式引用。