#r
#r
Вопрос:
Я использую функцию caRamel из пакета с тем же именем. Функция принимает другую функцию my_func в качестве аргумента….
caRamel(
fn=my_func,
other_caRamel_parameters...
)
my_func — это функция, принимающая уникальный параметр i (по дизайну, обязательный и задается функцией caRamel):
my_func <- function(i) {
require(somelib)
my_path = "C:/myfolder/"
do things with i
...
}
По замыслу, нет способа передать дополнительные аргументы функции my_func внутри функции caRamel, и мне приходится жестко кодировать все, например, переменную my_path, например, внутри my_func.
Тем не менее, я хотел бы иметь возможность передавать переменные my_path и другие в качестве параметров в функции caRamel следующим образом:
caRamel(
fn=my_func,
other_caRamel_parameters...,
my_path="C:/myfolder/", ...
)
с:
my_func <- function(i, my_path) {
require(somelib)
my_path = my_path
do things with i
...
}
Затем мне стало интересно, можно ли в этом случае написать «оболочку», чтобы дополнительные параметры можно было передавать в my_func? Какие могут быть варианты для достижения этого?
Комментарии:
1. Вам нужна фабрика функций? Я думаю, что это могло бы быть проще с более воспроизводимым примером. В противном случае вы всегда можете использовать
...
для передачи других аргументов в любую другую функцию.2. Привет, кажется, нет. Если я делаю это с функцией caRamel, я получаю ошибку неиспользуемого аргумента: Ошибка в caRamel(… неиспользуемый аргумент (my_path = «…»)…
3. Мы не можем точно сказать, что вы хотите сделать, без какого-либо примера.
Ответ №1:
Мы можем использовать {purrr} и {rlang} в пользовательской myCaRamel
функции, которая принимает только многоточие ...
в качестве аргумента.
Сначала мы фиксируем точки с rlang::list2(...)
помощью .
Затем мы получаем все формалы caRamel
функции в виде имен с rlang::fn_fmls_names
помощью .
Теперь мы различаем аргументы, которые входят в caRamel
функцию, и те, которые входят в вашу пользовательскую функцию.
Мы используем purrr::partial
для предоставления аргумента, который входит в ваш my_fun
.
Затем мы вызываем исходную caRamel
функцию, используя частичную функцию, которую мы создали вместе с аргументами, которые входят в caRamel
.
В приведенном ниже примере я rlang::expr
в последнем вызове, чтобы показать, что это работает. Пожалуйста, удалите expr()
вокруг последнего вызова, чтобы он действительно работал.
Недостатком является то, что каждый аргумент должен иметь правильное имя. Неназванные аргументы и частичное сопоставление не будут работать. Кроме того, если my_fun
и caRamel
содержат аргументы с похожими именами, они только входят caRamel
и не достигают my_fun
.
library(purrr)
library(rlang)
library(caRamel)
my_fun <- function(x, my_path) {
# use my_path
# and some x
}
myCaRamel <- function(...) {
dots <- rlang::list2(...)
caramel_args <- rlang::fn_fmls_names(caRamel)
caramel_args_wo_fun <- caramel_args["func" != caramel_args]
other_args <- names(dots)[!names(dots) %in% caramel_args]
my_fn <- dots[["func"]]
my_fn <- purrr::partial(my_fn, !!! dots[other_args])
rlang::expr( # just to show correct out put - delete this line
caRamel(func = my_fn,
!!! dots[names(dots) %in% caramel_args_wo_fun])
) # delete this line
}
myCaRamel(func = my_fun,
my_path = "C:/myfolder/",
nvar = 10)
#> caRamel(func = my_fn, nvar = 10)
Создано 2021-12-11 пакетом reprex (v2.0.1)