2016-12-28 1 views
1

J'ai un peu de mal à comprendre pourquoi, dans R, les deux fonctions ci-dessous, functionGen1 et functionGen2 se comportent différemment. Les deux fonctions tentent de renvoyer une autre fonction qui imprime simplement le nombre passé en argument au générateur de fonctions.Comprendre la fonction R évaluation paresseuse

Dans la première instance, les fonctions générées échouent car a n'est plus présent dans l'environnement global, mais je ne comprends pas pourquoi il doit l'être. J'aurais pensé qu'il a été passé comme un argument, et est remplacé par aNumber dans l'espace de noms de la fonction de générateur, et la fonction d'impression.

Ma question est: Pourquoi les fonctions de la liste list.of.functions1 ne fonctionnent plus lorsque a n'est pas défini dans l'environnement global? (Et pourquoi cela fonctionne pour le cas de list.of.functions2 et même list.of.functions1b)?

functionGen1 <- function(aNumber) { 
    printNumber <- function() { 
    print(aNumber) 
    } 
    return(printNumber) 
} 

functionGen2 <- function(aNumber) { 
    thisNumber <- aNumber 
    printNumber <- function() { 
    print(thisNumber) 
    } 
    return(printNumber) 
} 

list.of.functions1 <- list.of.functions2 <- list() 
for (a in 1:2) { 
    list.of.functions1[[a]] <- functionGen1(a) 
    list.of.functions2[[a]] <- functionGen2(a) 
} 

rm(a) 

# Throws an error "Error in print(aNumber) : object 'a' not found" 
list.of.functions1[[1]]() 

# Prints 1 
list.of.functions2[[1]]() 
# Prints 2 
list.of.functions2[[2]]() 

# However this produces a list of functions which work 
list.of.functions1b <- lapply(c(1:2), functionGen1) 

Répondre

3

Un exemple plus minime:

functionGen1 <- function(aNumber) { 
    printNumber <- function() { 
    print(aNumber) 
    } 
    return(printNumber) 
} 

a <- 1 
myfun <- functionGen1(a) 
rm(a) 
myfun() 
#Error in print(aNumber) : object 'a' not found 

Votre question ne concerne pas (namespaces c'est un concept lié à des forfaits), mais de la portée des variables et l'évaluation paresseuse.

L'évaluation paresseuse signifie que les arguments de fonction ne sont évalués que lorsqu'ils sont nécessaires. Jusqu'à ce que vous appelez myfun, il n'est pas nécessaire d'évaluer aNumber = a. Mais puisque a a été retiré alors, cette évaluation échoue.

La solution habituelle consiste à forcer l'évaluation explicite comme vous le faites avec votre functionGen2 ou, par exemple,

functionGen1 <- function(aNumber) { 
    force(aNumber) 
    printNumber <- function() { 
    print(aNumber) 
    } 
    return(printNumber) 
} 

a <- 1 
myfun <- functionGen1(a) 
rm(a) 
myfun() 
#[1] 1 
+0

Merci! Acceptera la réponse et changera le titre de la question pour mentionner l'évaluation paresseuse. Cela m'a fait trébucher et je sais maintenant ce qu'il faut rechercher. – kabdulla

+0

Si vous ne connaissez pas le terme, vous devriez également rechercher des "fermetures" puisque c'est ce que vous créez là. – Roland