R: Сделать именованные элементы в многоточии доступными (возможно, вложенными) в среде выполнения. - PullRequest
0 голосов
/ 06 октября 2018

Я хотел бы иметь возможность передавать именованные объекты в аргументах функции, которые были сопоставлены с многоточием (..., точками AKA), чтобы сделать их общедоступными в среде выполнения этой функции или выполняемых функцийвнутри этой среды, где бы она ни была определена, как если бы там были набраны аргументы.

Я пытался сделать это для функции, вложенной функции, определенной вне этой функции, и вложенной функции, определенной внутри этой функции,использование list2env (), которое должно возвращать элементы списка аргументов в среду parent.frame (), которая, как я понимаю, является вызывающей средой.Таким образом:

# Ellipsis in nested functions
inner_f1<- function(x){list2env(list(...)[-1L]); x + b}

outer_f <- function(x, ...){
  list2env(list(...)[-1L])
  in01 <- x + a
  inner_f2 <- function(x){list2env(list(...)[-1L]); print(ls()); x + c}
  in02 <- inner_f2(x)  
  in03 <- inner_f1(x)
  out <- list(in01, in02, in03)
}

outer_f(x=0, a=1, b=2, c=3)

Я пробовал это с и без ... в определениях вложенных функций, но ни одна из них не работает.Желаемым выводом будет:

$ in01
[1] 1
$ in02
[1] 2
$ in03
[1] 3

Файл справки R в разделе "Точки" не предоставляет никакой информации о передаче ... значений внутренним функциям, и единственный способ, в котором упоминается получение информации из ...с помощью метода .. (n).Он ссылается на «Введение в R», но пример par, похоже, неверно предполагает, что внутренней функции достаточно иметь свой собственный…, хотя код par (там не цитируется) получает содержимоеделать сложные вещи для args = list(...), и определение языка R также описывает метод list (...).Я не нашел заменитель идиомы (list (...)) [- 1], часто используемый в базовых пакетах R, официально документированный где-либо, но ни в коем случае ни this, ни eval (заменитель (alist (...)))) из "Advanced R" :: Нестандартная оценка, кажется, делает то, что я хочу.

Есть много ответов на вопросы о ... и вложенных функциях здесь на stackoverflow, но все 15или так, что я читаю, кажется, более специализированным, чем обобщенный метод, который я ищу.

Ответы [ 2 ]

0 голосов
/ 06 октября 2018

Альтернатива:

# note how I add an argument to specify the exact environment:
inner_f1<- function(x, env, ...){
  with(env, {list2env(list(...)); x + b})
 }

outer_f <- function(x, ...){

  # get the "address", i.e. the environment:
  here <- environment()

  # specify the environment in list2env:
  list2env(list(...), envir = here)
  in01 <- x + a

  inner_f2 <- function(x){list2env(list(...), envir = here); print(ls()); x + c}
  # alternatively, use: list2env(list(...), envir = parent.frame(n=2))

  in02 <- inner_f2(x)  

  in03 <- inner_f1(x, here)

  out <- list(in01, in02, in03)
  return(out)
}

outer_f(x=0, a=1, b=2, c=3)

[1] "x"
[[1]]
[1] 1

[[2]]
[1] 3

[[3]]
[1] 2

По сути, вам необходимо убедиться, что правильный «адрес» доступен для всех функций.

0 голосов
/ 06 октября 2018

Обратите внимание, что доступные переменные не идентичны переменным, перечисленным ls().В частности, ls() не будет перечислять переменные в родительской среде, но переменные в родительской среде по-прежнему доступны в качестве входных данных (а также в качестве выходных данных, если вы используете << -).Мы предполагаем, что вы просто хотите, чтобы переменные были доступны, и не заботитесь о <code>ls().(Если вы действительно хотите внедрить переменные из среды выполнения внешней функции во внутреннюю функцию, тогда перейдите ... к внутренней функции и используйте те же методы, которые показаны здесь для внешней функции.) Следующий пример показывает, что, хотя bдоступно, это не показано в выходных данных ls().

f1 <- function() { 
  b <- 1
  f2 <- function() { 
    print(b)  # will print the value of b showing b is accessible
    print(ls()) # no variables will be shown
  }
  f2() 
}
f1()

, что дает:

[1] 1
character(0)

Теперь вернемся к вопросу, вот несколько альтернатив:

1) с Попробуйте with:

inner_fun0 <- function() in1

outer_fun <- function(...) with(list(...), {
  inner_fun <- function() in1
  environment(inner_fun0) <- environment()
  list(in1, inner_fun(), inner_fun0())
})
outer_fun(in1 = 7)

давая:

[[1]]
[1] 7

[[2]]
[1] 7

[[3]]
[1] 7

2) list2env Альтернативой является использованиеlist2env вот так:

outer_fun2 <- function(...) {
  list2env(list(...), environment())
  inner_fun <- function() in1
  environment(inner_fun0) <- environment()
  list(in1, inner_fun(), inner_fun0())
}
outer_fun2(in1 = 7)

давая:

[[1]]
[1] 7

[[2]]
[1] 7

[[3]]
[1] 7

Вы можете создать дополнительные варианты, используя идеи в перезаписи переменной в родительской функции из внутренней функции, не делая переменную снаружиродительская функция

Также пакет proto мог бы использоваться для преобразования всего этого в объектно-ориентированную среду.

...