使用字符串作为函数的参数

时间:2020-02-14 09:44:22

标签: r eval

关于SO的这个主题有很多问题,包括关于如何计算表达式的this questionthis one表现出对使用eval的不同意见,而answer eval(substitute(.))技巧。 Hadley Wickham撰写的Advanced R的metaprogramming section是学习非标准评估(NSE)的一个很好的参考。 我注意到在答案中存在很多分歧,其中有些暗示了using strings as something to be evaluated的问题。

在这种情况下,我将字符串用作子函数的参数。
这是一个代表:

# Consider a little toy function:
little_fun <- function(z = 2, y = 1) {
     (z + 2) / y
}
little_fun()
#> [1] 4

# I can call little_fun() on lists of arguments:
z_list <- c(1,2,3)
purrr::map_dbl(.x = z_list, ~ little_fun(z = (.x)))   # This is basically a tidyverse equivalent for lapply()
#> [1] 3 4 5

# or also:
z_list <- c(1,2,3)
y_list <- c(-1, 0, 1)
purrr::map2_dbl(.x = z_list, .y = y_list, ~ little_fun(z = (.x), y = (.y)))  # again, similar to mapply()
#> [1]  -3 Inf   5

# But I also want to assign the parameters from a more general parent function:
big_fun <- function(par = "y") {

     stopifnot(par %in% c("z", "y"))

     par_list <- c(1,2,3)
     purrr::map_dbl(.x = par_list, ~ little_fun(par = (.x)))   # <--- key line <---
}
big_fun()
#> Error in little_fun(par = (.x)): unused argument (par = (.x))

我的问题:我仍然无法运行我的代码。

我的问题:为什么使用字符作为函数参数很不好?我应该避免这种情况吗?如何?我想了解如何改善我的推理能力并学习可用的替代方法。

1 个答案:

答案 0 :(得分:3)

我不同意chinsoon12对您的问题“我应该避免吗?”

的回答。

“保护自己免遭未来的愚蠢” – chinsoon12

话虽如此,动态分配的参数名称是do.call派上用场的地方。

big_fun <- function(par = "y") {
     stopifnot(par %in% c("z", "y"))
     par_list <- c(1,2,3)
     purrr::map_dbl(.x = par_list, ~do.call(little_fun, as.list(setNames(.x, par))))
}

big_fun()
# [1] 4.000000 2.000000 1.333333
big_fun("z")
# [1] 3 4 5

我个人有时会发现这样的程序令人费解且令人困惑,而在另一些情况下,这也许是优雅地解决某些问题的唯一方法。有时,它是最简洁,强大和有效的解决方案。

为了检查,我相信big_fun()本身应该与此匹配:

sapply(1:3, little_fun, z=2)
# [1] 4.000000 2.000000 1.333333
相关问题