Распаковка списков аргументов для многоточия в R
Меня смущает использование многоточия (...
) в некоторых функциях, т.е. как передать объект, содержащий аргументы, в качестве одного аргумента.
В Python это называется "распаковка списков аргументов", например
>>> range(3, 6) # normal call with separate arguments
[3, 4, 5]
>>> args = [3, 6]
>>> range(*args) # call with arguments unpacked from a list
[3, 4, 5]
В R, например, у вас есть функция file.path(...)
который использует многоточие. Я хотел бы иметь такое поведение:
> args <- c('baz', 'foob')
> file.path('/foo/bar/', args)
[1] 'foo/bar/baz/foob'
Вместо этого я получаю
[1] 'foo/bar/baz' 'foo/bar/foob'
где элементы args
не "распакованы" и оценены одновременно. Есть ли R эквивалент Pythons *arg
?
3 ответа
Синтаксис не такой красивый, но он делает свое дело:
do.call(file.path,as.list(c("/foo/bar",args)))
do.call
принимает два аргумента: функцию и список аргументов для вызова этой функции.
Вы можете извлечь информацию из многоточия, позвонив по телефону list(...)
внутри функции. В этом случае информация в многоточии упаковывается как объект списка. Например:
> foo <- function(x,...){
+ print(list(...))
+ }
> foo(1:10,bar = 'bar','foobar')
$bar
[1] "bar"
[[2]]
[1] "foobar"
Вы можете добиться желаемого поведения с помощью векторизованных функций, таких как file.path
с призывом к do.call
, который иногда проще использовать с оберткой splat
(в plyr
пакет)
> args <- c('baz', 'foob')
> library(plyr)
> splat(file.path)(c('/foo/bar', args))
[1] "/foo/bar/baz/foob"
Мне понадобилось время, чтобы найти его, но purrr
пакет имеет эквивалент plyr::splat
: это называется lift_dl
,
"Dl" в названии означает "точки в списке", так как это часть серии lift_xy
функции, которые можно использовать для "поднятия" области функции от одного вида ввода к другому, эти "виды" представляют собой списки, векторы и "точки".
поскольку lift_dl
вероятно, самый полезный из них, есть простой lift
псевдоним для этого.
Чтобы повторно использовать приведенный выше пример:
> library(purrr)
> args <- c('baz', 'foob')
> lift(file.path)(c('/foo/bar', args))
[1] "/foo/bar/baz/foob"