43 votes

Confondu par ...()?

Dans une autre question, sapply(substitute(...()), as.character) a été utilisé à l'intérieur d'une fonction pour obtenir les noms passés à la fonction. L' as.character partie sonne bien, mais ce qui sur terre n' ...() faire?

Ce n'est pas un code valide à l'extérieur de l' substitute:

> test <- function(...) ...()
> test(T,F)
Error in test(T, F) : could not find function "..."

Certains plus de cas de tests:

> test <- function(...) substitute(...())
> test(T,F)
[[1]]
T

[[2]]
F

> test <- function(...) substitute(...)
> test(T,F)
T

26voto

Josh O'Brien Points 68397

Voici un croquis de pourquoi ...() fonctionne de la manière qu'il le fait. Je vais remplir avec plus de détails et de références plus tard, mais cette touche sur les points clés.

  1. Avant d'effectuer la substitution sur l'un de ses composants, substitute() première analyse de R instruction.

  2. ...() analyse d'un objet d'appel, alors qu' ... analyse à un nom d'objet.

  3. ... est un objet spécial, destiné uniquement à être utilisé dans les appels de fonction. En conséquence, le code C qui implémente la substitution prend des mesures spéciales pour manipuler ... quand il se trouve dans un objet d'appel. De semblables précautions ne sont pas prises lors de l' ... se produit comme un symbole. (Le code est dans les fonctions do_substitute, substitute, et substituteList (surtout les deux derniers) en R_SRCDIR/src/main/coerce.c.)

Ainsi, le rôle de l' () en ...() est à cause de la déclaration afin d'être analysée comme un appel (aka la langue) de l'objet, de sorte que la substitution sera de retour le déploiement complet de la valeur des points. Il peut paraître surprenant qu' ... se substituer, même quand il est à l'extérieur de l' (), mais: (a) les appels sont stockées en interne sous forme de liste d'objets et (b) de la C code semble pas faire de distinction entre le premier élément de cette liste, et les suivants.


Juste une note de côté: étude de comportement de l' substitute ) ou les classes d'objets divers, je trouve utile de mettre en place un petit bac à sable, comme ceci:

f <- function(...) browser()
f(a = 4, 77, B = "char")
## Then play around within the browser
class(quote(...))  ## quote() parses without substituting
class(quote(...()))
substitute({...})
substitute(...(..., X, ...))
substitute(2 <- (makes * list(no - sense))(...))

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X