Подтвердить что ты не робот

Можно ли удалить элемент в... (точка-точка) и передать его?

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

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 )

Изменить
Прошу прощения за путаницу. Я зафиксировал child(). Цель состояла в том, чтобы иметь дочерний список содержимого...

Edit2
Здесь более реальный пример (но все же довольно простой, поэтому мы можем иметь полезный разговор об этом). Родитель вызывается через рекурсию. Родитель должен знать глубину рекурсивного вызова. Звонящие за пределами родителя не должны знать о "глубине" и не должны устанавливать его при вызове 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    
}
4b9b3361

Ответ 1

Один из способов управления этими вещами состоит в том, чтобы обернуть функцию 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(), возможно, ближе всего к вашему намерению.

Ответ 2

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

> 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)
}

Ответ 3

Вот пример того, как получить элементы из... и удалить элемент, а затем я вызываю следующую функцию с 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 любит имена списков, имена которых являются именами аргументов, а значениями в списке являются значения аргументов. Это в файле справки, но я немного боролся с этим, прежде чем, наконец, выяснил это.

Ответ 4

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

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 только здесь.

Ответ 5

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

xmax-xmin -> xrange

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

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