R语言:如何通过...参数预设函数参数并构建可传递新函数?
解决R中通过省略号预设函数参数并传递的问题
需求是实现foo函数,接收通过...传入的额外参数,构建绑定了这些参数的新函数,传递给其他函数,使得调用foo(x, paste, collapse = ", ")等价于调用bar(x, FUN = \(x) paste(x, collapse = ", "))。
错误原因分析
你最初的foo实现出现错误,核心是变量作用域冲突:
foo <- function(v, FUN, ...) { FUN <- \(x) FUN(x, ...) FunAssign(FUN, v) }
这里重新赋值了FUN变量,匿名函数内部的FUN会优先引用这个新定义的匿名函数本身,而非传入的原始paste函数,最终导致调用时出现参数不匹配的错误。
正确实现方法
方法1:手动规避作用域冲突
通过将原始函数保存到新变量,避免覆盖导致的引用混乱:
# 辅助函数 FunAssign <- function(f, x) f(x) # 修正后的foo函数 foo <- function(v, FUN, ...) { original_FUN <- FUN NEWFUN <- \(x) original_FUN(x, ...) FunAssign(NEWFUN, v) } # 测试调用 foo(letters[1:5], paste, collapse = ", ") #> [1] "a, b, c, d, e"
方法2:使用purrr::partial简化实现
如果允许使用purrr包,可直接用partial函数快速绑定参数,无需手动处理作用域:
library(purrr) foo <- function(v, FUN, ...) { NEWFUN <- partial(FUN, ...) FunAssign(NEWFUN, v) } # 测试调用同样有效 foo(letters[1:5], paste, collapse = ", ") #> [1] "a, b, c, d, e"
为什么baz可以正常运行
你的baz函数没有覆盖FUN参数,匿名函数内部的FUN直接引用函数参数中的原始函数,不存在作用域冲突:
baz <- function(FUN, ...) \(x) FUN(x, ...) baz(paste, collapse = ", ")(letters[1:5]) #> [1] "a, b, c, d, e"
内容的提问来源于stack exchange,提问作者Joseph Wood
相关产品推荐
相关产品推荐

