2011-07-15 24 views
18

W dokumentacji sapply i replicate jest ostrzeżenie o użyciu ...Używanie „...” i «powielać»

Teraz mogę przyjąć je jako takie, ale chciałby, aby zrozumieć, co jest za nim. Dlatego stworzyliśmy ten mały contrived przykład:

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) 

Może zrobiłem coś oczywistego strasznie źle, ale uważam, że wynik ten raczej denerwujące. Więc może ktoś mi wyjaśnić, dlaczego we wszystkich powyższych wywołań outerfunction, otrzymuję ten wynik:

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 

Tak jak mówiłem: docs wydają się ostrzec o tym, ale nie widzę, dlaczego tak jest .

Odpowiedz

11

?replicate, w sekcji Przykłady, wyraźnie stwierdza, że ​​to, co próbujesz zrobić, nie działa i nie będzie działać. W sekcji Note z ?replicate mamy:

 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’. 

A jeśli spojrzymy na przykładach widzimy:

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

Moje czytanie docs jest to, że robią znacznie więcej niż ostrzec o użyciu ... w wywołaniach replicate(); jednoznacznie udokumentują, że nie działa. Większość dyskusji w tym pliku pomocy odnosi się do innych funkcji, niekoniecznie do adresu replicate().

+0

pamiętać, że w tym przykładzie, zdarzenie „poprawny” sposób nie działa prawidłowo - jest replikowane 'x' razy (3) zamiast' n' razy (5). – James

+1

@ James - nie w moim systemie. Dostaję matrycę 2 * 5 dla 'bar (5, x = 3)' –

+0

Ups, mój błąd. Miał literówki podczas transkrypcji przykładów. – James

6

Jeśli spojrzeć na kod dla replicate:

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

Widać, że funkcja jest wyliczana w ramce nadrzędnej, gdzie ... z funkcji wywołującej już nie istnieje.

1

Tam faktycznie jest sposobem, aby to zrobić:

# 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

Alternatywnym sposobem, aby to zrobić:

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)