2016-12-28 6 views
1

以下の2つの関数Rで、なぜfunctionGen1functionGen2の動作が異なるのか、少し迷っています。両方の関数は、引数として渡された数値を単に関数ジェネレータに出力する別の関数を返そうとします。R関数の遅延評価について

最初のインスタンスでは、グローバル環境ではaが存在しなくなったため、生成された関数は失敗しますが、なぜそれが必要なのか分かりません。私はそれが引数として渡されたと思っていて、ジェネレータ関数の名前空間と印刷機能のaNumberに置き換えられました。

質問: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 

は、あなたの質問は(つまり、パッケージに関連する概念です)名前空間についてではなく、変数のスコープと遅延評価について。

遅延評価とは、関数引数が必要なときにのみ評価されることを意味します。 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