Могу ли я удалить элемент в ... (точка-точка-точка) и передать его дальше? - PullRequest
21 голосов
/ 11 августа 2011

Можно ли удалить элемент из ... и передать ... на другие функции?Мои первые две попытки потерпели неудачу:

parent = function(...)
{

   a = list(...)
   str(a)
   a$toRemove = NULL  
   str(a)

   # attempt 1   
   child(a)   

   # attempt 2
   child( ... = a )
}


child = function(...)
{
  a = list( ... )
  str(a)
}

parent( a = 1 , toRemove = 2 )

Редактировать
Извините за путаницу.Я исправил ребенка ().Намерение состояло в том, чтобы иметь дочерний список содержимого ...

Edit2
Вот еще пример из реальной жизни (но все же довольно простой, поэтому мы можем иметь полезную беседу оЭто).Родитель вызывается через рекурсию.Родителю нужно знать глубину рекурсивного вызова.Вызывающие стороны вне parent не должны знать о «глубине» и не должны устанавливать ее при вызове parent ().Родитель вызывает другие функции, в этом случае child ().Дочерним элементам нужны значения в ... Очевидно, что дочернему элементу не нужна «глубина», потому что родительский объект сгенерировал его для собственного использования.

parent = function( ... )
{

   depth = list(...)$depth      
   if ( is.null( depth ) )
   {
       depth = 1
   }  
   print( depth )

   # parent needs value of depth to perform various calculations (not shown here)

   if ( depth == 5 )
   {
       return()
   }
   else
   {
      # child doesn't need "depth" in ...
      child( ... ) 
   }

   # yikes!  now we've added a second, third, etc. depth value to ...
   parent( depth = depth + 1 , ... )

}


child = function(...) 
{       
    # does some magic    
}

Ответы [ 5 ]

25 голосов
/ 11 августа 2011

Один из способов манипулировать этими вещами - это обернуть функцию child внутри parent и использовать определение, которое помещает любые аргументы, которые вы не хотите передавать, в child после ... аргумент. Например:

parent <- function(...) {
    localChild <- function(..., toRemove) child(...)
    localChild(...)
}
child <- function(a) {
    a + 10
}

> parent(a = 1, toRemove = 10)
[1] 11

Другой способ - использовать do.call():

parent2 <- function(...) {
    a <- list(...)
    a$toRemove <- NULL
    do.call(child2, a)
}
child2 <- function(b) {
    b + 10
}
> parent2(b = 1, toRemove = 10)
[1] 11

В зависимости от вашего фактического варианта использования, do.call(), возможно, ближе всего к тому, что вы намеревались с помощью вашего Вопроса.

5 голосов
/ 11 августа 2011

Ваша дочерняя функция ошибочна.Попробуйте

> child(a=1)
Error in str(a) : object 'a' not found

edit: больше не применяется.

Аргумент ... должен использоваться только для передачи параметров в следующую функцию.Вы не можете легко получить параметры оттуда, если не конвертируете их в список.Таким образом, ваша дочерняя функция может быть:

child <- function(...)
{
  mc <- match.call()  # or mc <- list(...)
  str(mc$a)
}

Что не имеет смысла.Вы не можете знать, указал ли пользователь a или нет.Правильный способ будет включать a в качестве аргумента в вашу функцию.... - передать аргументы следующему:

child <- function(a, ...){
    str(a,...)
}

Тогда вы можете сделать:

parent <- function(...){

   mc <- match.call()
   mc$toRemove <- NULL
   mc[[1L]] <- as.name("child")
   eval(mc)

}

или использовать конструкции list(...) и do.call(), предложенные @Gavin,Преимущество match.call() состоит в том, что вы также можете включать не точечные аргументы.Это позволяет вашей родительской функции указывать значения по умолчанию для ребенка:

parent <- function(a=3, ...){
    ... (see above)
}
4 голосов
/ 11 августа 2011

Вот пример того, как извлечь элементы из ... и удалить элемент, а затем я вызываю следующую функцию с помощью do.call:

parent <- function(...){
   funArgs <-  list(...)
   str(funArgs)
   ## remove the second item
   newArgs <- funArgs[-2]
   str(newArgs)
   ## if you want to call another function, use do.call
   do.call(child, newArgs)
  }

child = function(...)
{
  cat("Don't call me a child, buddy!\n")
  a <- list(...)
  str(a)
}


parent(a=1, b=2, c=3)

Если вам нужно добавить больше элементов к вашим аргументам, а не удалять аргументы, имейте в виду, что do.call любит именованные списки, где имена - это имена аргументов, а значения списка - значения аргументов. Это в файле справки, но я немного поборолся с этим, прежде чем окончательно разобраться.

3 голосов
/ 11 августа 2011

Вы получаете несколько хороших ответов, но вот кое-что простое, касающееся вашего конкретного примера:

parent = function(...)
{

   a = list(...)
   str(a)
   a$toRemove = NULL  
   str(a)

   # attempt 1   
   child(a)   

   # attempt 2
   #child(...)
}

child = function(...)
{
    a <- as.list(...)   
    str(a)
}

parent( a = 1 , toRemove = 2 )

, который возвращает:

List of 2
 $ a       : num 1
 $ toRemove: num 2
List of 1
 $ a: num 1
List of 1
 $ a: num 1

В исходной версии возникла ошибка,поскольку a не было определено в child.Тогда простое использование as.list(...) в child (в отличие от list(...)), кажется, генерирует желаемый результат.Обратите внимание, что я использую вашу попытку 1 только здесь.

0 голосов
/ 11 августа 2011

Я не думаю, что перечисленные ответы решают проблему, или, по крайней мере, не так, как я ее читаю.Предположим, что вы хотите передать некоторые параметры, такие как, например, «xmax» и «xmin», потомку (...) как фактические переменные?
в дочерней среде, он хочет видеть переменные с именами «xmax» и «xmin»и примеры, представленные до сих пор, кажется, не делают эти переменные доступными.Попробуйте вставить строку типа

xmax-xmin -> xrange

в функцию child (), и она выдаст ошибку.
Суть исходного вопроса, как я думал, заключалась в том, чтобы разрешить передачу подмножестванеобязательные переменные "..." для child ().Вы можете адаптировать решения для простых случаев, например, sum (...), где работает sum (unlist (the_modified_list)).В более общем случае я все еще не вижу решения.Возможно, нам нужно поднять эту проблему в список рассылки R-help.

Редактировать: см. Подробную презентацию по адресу http://ucfagls.wordpress.com/2011/07/23/passing-non-graphical-parameters-to-graphical-functions-using/

...