R语言有一个很好的功能,用于定义可以采用可变数量参数的函数 . 例如,函数 data.frame
接受任意数量的参数,并且每个参数都成为结果数据表中列的数据 . 用法示例:
> data.frame(letters=c("a", "b", "c"), numbers=c(1,2,3), notes=c("do", "re", "mi"))
letters numbers notes
1 a 1 do
2 b 2 re
3 c 3 mi
函数的签名包括省略号,如下所示:
function (..., row.names = NULL, check.rows = FALSE, check.names = TRUE,
stringsAsFactors = default.stringsAsFactors())
{
[FUNCTION DEFINITION HERE]
}
我想写一个类似的函数,获取多个值并将它们合并为一个返回值(以及进行一些其他处理) . 为了做到这一点,我需要弄清楚如何"unpack" ...
函数's arguments within the function. I don'知道如何做到这一点 . data.frame
的函数定义中的相关行是 object <- as.list(substitute(list(...)))[-1L]
,我无法理解 .
那么如何将省略号从函数的签名转换为例如列表呢?
更具体地说,如何在下面的代码中编写 get_list_from_ellipsis
?
my_ellipsis_function(...) {
input_list <- get_list_from_ellipsis(...)
output_list <- lapply(X=input_list, FUN=do_something_interesting)
return(output_list)
}
my_ellipsis_function(a=1:10,b=11:20,c=21:30)
编辑
似乎有两种可能的方法来做到这一点 . 它们是 as.list(substitute(list(...)))[-1L]
和 list(...)
. 但是,这两者并没有完全相同 . (有关差异,请参阅答案中的示例 . )任何人都能告诉我它们之间的实际区别是什么,我应该使用哪一个?
6 回答
我阅读了答案和评论,但我发现没有提到几件事:
data.frame
使用list(...)
版本 . 代码片段:object
用于对列名进行一些魔术,但x
用于创建最终data.frame
.要使用未评估的
...
参数,请查看使用match.call
的write.csv
代码 .language
类型 . 第一个对象是symbol
-list
,第二个是表达式1:10
,依此类推 . 这解释了为什么需要[-1L]
:它从...
中提供的参数中删除了预期的symbol
(因为它始终是一个列表) .由于德克声明
substitute
返回"parse tree the unevaluated expression" .当你调用
my_ellipsis_function(a=1:10,b=11:20,c=21:30)
然后...
"creates"一个参数列表:list(a=1:10,b=11:20,c=21:30)
和substitute
使它成为四个元素的列表:第一个元素没有名称,这在Dirk答案中是
[[1]]
. 我使用以下方法获得此结果str
来检查函数中的对象 .没关系 . 让我们看看
substitute
版本:不是我们需要的 . 您将需要其他技巧来处理这些类型的对象(如
write.csv
) .如果你想使用
...
那么你应该像Shane一样使用它来回答list(...)
.您可以使用
list()
将省略号转换为列表,然后对其执行操作:所以你的
get_list_from_ellipsis
函数只不过是list
.一个有效的用例是在你想要传入未知数量的对象进行操作的情况下(如
c()
或data.frame()
的例子) . 当你事先知道每个参数时,使用...
并不是一个好主意,但是,它会给参数字符串增加一些模糊性和进一步的复杂性(并使任何其他用户都不清楚函数签名) . 参数列表是功能用户的重要文档 .否则,它对于您希望将参数传递给子函数而不将它们全部暴露在您自己的函数参数中的情况也很有用 . 这可以在功能文档中注明 .
只是为了补充Shane和Dirk的回答:比较有趣
同
就目前而言,任何一个版本在
my_ellipsis_function
中都适合您的目的,尽管第一个版本显然更简单 .你已经给出了一半的答案 . 考虑
所以这从调用中获取了两个参数
a
和b
并将其转换为列表 . 那不是你要的吗?这按预期工作 . 以下是交互式会话:
相同,除了默认参数:
如您所见,如果默认值不是您在特定情况下所需的值,则可以使用此参数将“额外”参数传递给函数中的函数 .
我认为这是你所期待的(见图) . a1,a2,a3,a4是一些任意向量,'catt'是接受任意数量参数并返回输入参数的连接向量的函数 .