2014-07-11 1 views
2

Dans le langage R, supposons que j'ai une fonction ff (jj, kk, mm). Je voudrais que la fonction appelante (ou appeler un être humain dans une session interactive) soit capable de faire dépendre de façon arbitraire mm sur jj et kk au moment de l'appel.Pouvez-vous permettre à une fonction R de voir les valeurs de ses propres formats lors de l'évaluation?

Pour concrétude, on suppose que:

ff <- function(jj, kk, mm){ 
    xx <- jj + kk 
    out<- xx/mm 
    out 
} 

Puis au moment de l'exécution, je veux mettre mm <- jj*kk. i.e. .:

ff(2, 3, (jj*kk)) 

ce rendement:

Error in ff(2, 3, (jj * kk)) : object 'jj' not found 

Cette erreur est pas jeté jusqu'à mm est évaluée, à savoir après jj et kk ont déjà été évalués avec succès. Donc, ils sont ensuite évalués une deuxième fois avec différentes règles de portée. Je comprends que c'est la portée R-standard. Je demande, puis-je écrire la fonction de telle manière qu'elle me laisse mm un nombre simple, ou une fonction des autres arguments formels, à condition que ces arguments aient été ou puissent être évalués avant que mm soit requis?

Notez que je ne demande pas si je devrais le faire. Je vais faire semblant d'être poli avec les gens qui offrent des vues sur cette dernière question. Je ne demande pas non plus si je peux pré-calculer jj et remettre à la main le numéro prédigéré. Je sais c'est une réponse plausible, mais cela ne fonctionne pas pour des raisons que j'ai simplifiées sur le problème.

+2

Juste pour illustrer le point à * pourquoi * vous ne devriez pas le faire, cela conduit à: 'jj = 99; kk = 101; ff (2,3, (jj * kk)) 'en ignorant les valeurs de' jj' et 'kk' que vous venez de définir car elles sont évaluées dans la fonction lorsqu'elles sont égales respectivement à 2 et 3. Cela surprendrait tout utilisateur R qui n'a pas lu la documentation de 'ff' ... – Spacedman

+0

Je ne suis pas sûr de vous suivre. Si j'ai une fonction f <-fonction (x) {x^2}, et je fais x <- 3, f (x), je m'attends à en obtenir 9. Mais si je fais f (2) je m'attends à avoir 4 Attends ... je pense que je vois. Vous imaginez quelqu'un d'autre utilisant cette fonction, qui ne l'a pas simplement écrit, oui? Je suis assez sûr que ce projet est unique, donc la question ne se pose pas dans mon cas. Mais je vois comment ça pourrait. – andrewH

+0

Vous pouvez trouver http://adv-r.had.co.nz/Computing-on-the-language.html utile – hadley

Répondre

5

En l'état actuel, votre fonction ff() ne fonctionne pas parce supplied arguments are evaluated in the context of the calling environment, dont le point ni vue ni jjkk sont « visibles ».

Pour évaluer la déclaration fournie à mm dans le cadre du propre cadre d'évaluation de la fonction, utilisez eval(substitute()), comme ceci:

ff <- function(jj, kk, mm){ 
    mm <- eval(substitute(mm)) 
    xx <- jj + kk 
    out<- xx/mm 
    out 
} 

ff(2, 3, (jj*kk)) 
## [1] 0.8333333 
+1

Aussi, les parens autour de '(jj * kk)' ne sont pas nécessaires - fonctionne aussi bien sans eux. – Spacedman

+0

Merci Josh! Cela fait le travail précisément. Cela peut mériter sa propre question, mais j'ai un suivi. Que faire si vous voulez faire référence à l'environnement de la fonction, comme dans: LookHere <- function (X) {eval (substitut (X), envir = parent.frame (n = 0))}; ff <- function (jj, kk, mm) { mm <- LookHere (mm) xx <- jj + kk out <- xx/mm sur } ff (2, 3, (jj * kk)) Clairement parent.le cadre (n = 0) est faux. Qu'est-ce qui est juste? – andrewH

+0

@andrewH - Bonjour. Je n'ai pas le temps de l'expliquer maintenant, mais il semble que vous voulez quelque chose comme LookHere <- function (X) eval (do.call (substitut, liste (substitut (X), env = parent.frame (n = 1))), env = parent.frame (n = 1)) ' –

Questions connexes