2016-12-28 7 views
1

У меня возникли проблемы с пониманием того, почему в R две функции ниже, functionGen1 и functionGen2 ведут себя по-другому. Обе функции пытаются вернуть другую функцию, которая просто печатает число, переданное в качестве аргумента генератору функций.Понимание функции R ленивая оценка

В первом случае сгенерированные функции не сработали, посколькубольше не присутствует в глобальной среде, но я не понимаю, почему это должно быть. Я бы подумал, что это передано как аргумент и заменено на aNumber в пространстве имен функции генератора и функции печати.

Мой вопрос: Почему функции в списке list.of.functions1 больше не работают, если a не определен в глобальной среде? (И почему это работает на случай list.of.functions2 и даже 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) 

ответ

3

Более минимальный пример:

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 

Ваш вопрос не о пространствах имен (это понятие, связанное с пакетами), но о видимости переменных и ленивые вычисления.

Lazy оценка означает, что аргументы функции оцениваются только тогда, когда они необходимы. Пока вы не назовете myfun, нет необходимости оценивать aNumber = a. Но так как a был удален, эта оценка не удалась.

Обычное решение, чтобы заставить оценку явно, как вы делаете с вашим functionGen2 или, например,

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

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

Спасибо! Примите ответ и измените название вопроса, чтобы упомянуть ленивую оценку. Это подтолкнуло меня и теперь знаю, что искать. – kabdulla

+0

Если вы не знаете этот термин, вы также должны искать «закрытие», так как это то, что вы там создаете. – Roland