R语言中如何隐式传递函数调用栈的所有参数?
更简洁的参数传递方案:用
match.call() 这问题问得太实用了——谁都不想每次修改函数参数时,还要同步更新内部的函数调用语句对吧?其实R里有个比environment()更靠谱、更简洁的方法,完全不用显式指定参数,还能避免内部变量的干扰。
先回顾下你的场景代码:
f2 <- function(...) { print(list(...)) } f1 <- function(x, y = 1, ...) { z <- 20; f2(x, y, ...) } f1(5, k = 6)
你想实现的是:不管f1的参数怎么调整,都能自动把所有参数(包括默认参数)传给f2,不用手动写x, y, ...。
最优解决方案
直接用match.call()获取当前函数的调用参数,去掉函数名后传给do.call(f2, ...)就行:
f1 <- function(x, y = 1, ...) { z <- 20 # 捕获调用参数,移除函数名后转成列表 call_args <- as.list(match.call())[-1] do.call(f2, call_args) }
测试一下f1(5, k = 6),输出和原代码完全一致:
[[1]] [1] 5 $y [1] 1 $k [1] 6
而且如果以后你给f1加新参数(比如f1 <- function(x, y=1, a=3, ...)),完全不用修改f2的调用语句,新参数会自动被传递过去。
为什么这个方法更好?
和你之前用environment()的方法比,它有两个核心优势:
- 不会混入内部变量:
as.list(environment())如果在函数内部定义变量(比如z <-20)之后调用,会把z也包含进去,导致错误传递给f2——你必须把它放在函数开头才能避免。而match.call()只捕获调用时传入的参数,完全不管函数内部定义的变量,安全得多。 - 自动补全默认参数:它会把
f1中没显式传入的默认参数(比如例子里的y=1)自动补全到参数列表里,和原代码的行为完全一致。如果用sys.call()的话,只会保留显式传入的参数,默认参数不会被传递,这不符合你的需求。
内容的提问来源于stack exchange,提问作者Andrei




