Dans mon développement R j'ai besoin d'envelopper les primitives de fonction dans proto
objets de sorte qu'un certain nombre d'arguments peuvent être automatiquement transmis aux fonctions lorsque la méthode $perform()
de l'objet est appelée. L'appel de fonction se passe en interne via do.call()
. Tout va bien, sauf lorsque la fonction tente d'accéder à des variables à partir de la fermeture dans laquelle elle est définie. Dans ce cas, la fonction ne peut pas résoudre les noms.Environnement chaînage dans R
Voici l'exemple le plus petit que j'ai trouvé qui reproduit le comportement:
library(proto)
make_command <- function(operation) {
proto(
func = operation,
perform = function(., ...) {
func <- with(., func) # unbinds proto method
do.call(func, list(), envir=environment(operation))
}
)
}
test_case <- function() {
result <- 100
make_command(function() result)$perform()
}
# Will generate error:
# Error in function() : object 'result' not found
test_case()
J'ai un test testthat
reproductible qui génère aussi beaucoup de sortie de diagnostic. La sortie de diagnostic m'a bloqué. En cherchant la chaîne d'environnement parent, mon code de diagnostic, qui vit dans la fonction, trouve et imprime la même variable que la fonction ne parvient pas à trouver. See this gist..
Comment l'environnement de do.call
peut être configuré correctement?
Merci pour vos nombreux suivis sur cette question. Pourriez-vous m'aider à comprendre pourquoi cela fonctionne? Est-ce que ça va comme ceci: ** (1) ** le '.' dans l'appel de' proto() 'fait référence au cadre d'évaluation/environnement de l'appel à' make_command() ', qui devient ainsi le parent (ie '.super') du nouvel objet proto; de sorte que ** (2) ** quand 'operation' n'est pas trouvé dans l'objet proto, il est recherché et trouvé dans son' .super'; et alors ** (3) ** 'operation' lui-même a comme environnement le cadre/environnement d'évaluation de l'appel à' test_case() '(où' result' vit aussi)? –
Un objet proto est un environnement. L'objet proto a ici un composant, 'perform', qui est une fonction/méthode. L'environnement de 'perform' est mis à l'objet proto quand il est inséré alors quand' perform' s'exécute, il cherche d'abord 'operation' dans l'objet proto et quand il n'est pas trouvé il regarde dans le parent de l'objet proto. Le parent de l'objet proto n'a pas été spécifié, donc il est par défaut dans l'environnement dans lequel l'objet 'proto' a été défini - qui est l'environnement dans le cadre d'exécution de' make_command' et là, il trouve 'operation' comme argument. Voir la nouvelle FAQ sur la page d'accueil proto. –
Merci pour les questions/commentaires supplémentaires et merci pour la nouvelle FAQ. – Sim