2011-07-15 12 views
18

En la documentación de sapply y replicate hay una advertencia respecto al uso de ...El uso de "..." y 'reproducir'

Ahora, puedo aceptarlo como tal, pero me gustaría entender lo que está detrás de él. Así que he creado este pequeño ejemplo artificioso:

innerfunction<-function(x, extrapar1=0, extrapar2=extrapar1) 
{ 
    cat("x:", x, ", xp1:", extrapar1, ", xp2:", extrapar2, "\n") 
} 

middlefunction<-function(x,...) 
{ 
    innerfunction(x,...) 
} 

outerfunction<-function(x, ...) 
{ 
    cat("Run middle function:\n") 
    replicate(2, middlefunction(x,...)) 
    cat("Run inner function:\n") 
    replicate(2, innerfunction(x,...)) 
} 

outerfunction(1,2,3) 
outerfunction(1,extrapar1=2,3) 
outerfunction(1,extrapar1=2,extrapar2=3) 

Tal vez he hecho algo obvio muy mal, pero me parece el resultado de este lugar inquietante. Entonces, ¿puede alguien explicarme por qué, en todas las llamadas anteriores a outerfunction, consigo esta salida:

Run middle function: 
x: 1 , xp1: 0 , xp2: 0 
x: 1 , xp1: 0 , xp2: 0 
Run inner function: 
x: 1 , xp1: 0 , xp2: 0 
x: 1 , xp1: 0 , xp2: 0 

Como he dicho: los documentos parecen advertir para esto, pero no veo por qué esto es así .

Respuesta

11

?replicate, en la sección de Ejemplos, nos dice explícitamente que lo que está tratando de hacer no funciona y no funcionará. En la sección Note de ?replicate tenemos:

 If ‘expr’ is a function call, be aware of assumptions about where 
    it is evaluated, and in particular what ‘...’ might refer to. You 
    can pass additional named arguments to a function call as 
    additional named arguments to ‘replicate’: see ‘Examples’. 

Y si nos fijamos en los ejemplos, vemos:

## use of replicate() with parameters: 
foo <- function(x=1, y=2) c(x,y) 
# does not work: bar <- function(n, ...) replicate(n, foo(...)) 
bar <- function(n, x) replicate(n, foo(x=x)) 
bar(5, x=3) 

Mi lectura de los documentos es que lo hacen mucho más de lo que advierten sobre el uso de ... en replicate() llamadas; ellos explícitamente documentan que no funciona. Gran parte de la discusión en ese archivo de ayuda se relaciona con el argumento ... de las otras funciones, no necesariamente con replicate().

+0

Tenga en cuenta que en el ejemplo, el evento de manera "correcta" no funciona correctamente - Se repite 'x' veces (3) en lugar de' n' veces (5). – James

+1

@James - no está en mi sistema. Obtengo una matriz de 2 * 5 para 'bar (5, x = 3)' –

+0

Vaya, mi error. Tuve un error al transcribir los ejemplos. – James

6

Si nos fijamos en el código para replicate:

> replicate 
function (n, expr, simplify = TRUE) 
sapply(integer(n), eval.parent(substitute(function(...) expr)), 
    simplify = simplify) 
<environment: namespace:base> 

se ve que la función se evalúa en el marco padre, donde el ... de su función de llamada ya no existe.

1

realidad, hay una manera de hacer esto:

# Simple function: 
ff <- function(a,b) print(a+b) 

# This will NOT work: 
testf <- function(...) { 
    replicate(expr = ff(...), n = 5) 
} 
testf(45,56) # argument "b" is missing, with no default 

# This will: 
testf <- function(...) { 
    args <- as.list(substitute(list(...)))[-1L] 
    replicate(expr = do.call(ff, args), n = 5) 
} 
testf(45,56) # 101 
0

Una forma alternativa de hacer eso:

g <- function(x, y) x + y 

f <- function(a = 1, ...) { 
    arg_list <- list(...) 
    replicate(n = 3, expr = do.call(g, args = arg_list)) 
} 

f(x = 1, y = 2) 
Cuestiones relacionadas