2015-08-16 3 views
12

Wenn wir den Rumpf einer Funktion mit Punkten ... in seiner Argumentliste anzeigen, können wir normalerweise die Funktion finden, die diese Punkteargumente empfängt.Wo werden fehlende Punkte (`...`) verarbeitet?

Zum Beispiel können wir im Körper von sapply() sehen, dass die Punkte Argumente durch lapply() übergeben werden.

sapply 
# function (X, FUN, ..., simplify = TRUE, USE.NAMES = TRUE) 
# { 
#  FUN <- match.fun(FUN) 
#  answer <- lapply(X = X, FUN = FUN, ...) 
#  ## rest of function body 
# } 
# <bytecode: 0x000000000e05f0b0> 
# environment: namespace:base> 

jedoch in lapply() gibt es Punkte ... in der Argumentliste aber nicht in dem Funktionskörper.

lapply 
# function (X, FUN, ...) 
# { 
#  FUN <- match.fun(FUN) 
#  if (!is.vector(X) || is.object(X)) 
#   X <- as.list(X) 
#  .Internal(lapply(X, FUN)) 
# } 
# <bytecode: 0x0000000009414f08> 
# <environment: namespace:base> 

Also, wo die Punkte ... Argumente in lapply() verarbeitet werden? Wo werden sie hingeführt? Wir können sie nicht an match.fun() übergeben. Ich gehe davon aus, dass sie in .Internal() übergeben werden, aber ich sehe keinen Grund dafür, dass dies funktioniert, wenn ich nicht sehe, dass sie an irgendeine Funktion im Funktionskörper übergeben werden.

Antwort

13

Sie sind nicht explizit -.Internal vergangen, aber ich glaube, sie zu do_lapply verfügbar sind (in src/main/apply.c) über Dynamikumfang. Die Scoping-Regeln können etwas anders als üblich sein, da .Internal eine primitive Funktion ist.

Sie können sehen, dass ... (R_DotsSymbol) zum Funktionsaufruf lapply hinzugefügt wird, so dass sie für den Funktionsaufruf auf jedem Listenelement verfügbar sind. tmp entspricht ungefähr X[[i]] und R_fcall entspricht ungefähr FUN(X[[i]], ...).

SEXP tmp = PROTECT(LCONS(R_Bracket2Symbol, 
     LCONS(X, LCONS(isym, R_NilValue)))); 
SEXP R_fcall = PROTECT(LCONS(FUN, 
      LCONS(tmp, LCONS(R_DotsSymbol, R_NilValue))));