2012-05-13 9 views
3

誰かが以下のスニペットがどうして動くのか説明してもらえますか?文字列を返す関数のリストを構築する

l <- list() 
AddFn <- function(str) { l[[length(l) + 1]] <<- function() { return(str) }} 
AddFn("hello") 
AddFn("there") 
l[[1]]() # Returns "hello" as expected 
l[[2]]() # Returns "there" as expected 
for (letter in letters) AddFn(letter) 
l[[3]]() # Returns "z" 

私はl[[3]]()が "a"を返すと予想しました。私は何が欠けていますか?私のAddFn関数は正確に何をしますか?

は、事前に

エイドリアン

+4

+1私の脳を傷つける機能を書くため。 – joran

答えて

7

遅延評価をいただき、ありがとうございます、多くの場合、返されたばかりのループの最後の評価につながります。代わりにこれを試してください:

AddFn <- function(str) { force(str); l[[length(l) + 1]] <<- function() { return(str) }} 
+2

力を教えてくれる+1。 – Dason

7

これは厄介です。 str引数はletterを返すという約束に設定されていますが、l[[3]]()で呼び出されるまで実際には評価されません。したがって、その時点の値が使用されます!

あなたが最後の部分を変更した場合:

for (letter in letters) AddFn(letter) 
letter="foo" 
l[[3]]() # Returns "foo" 

...あなたはより明確にそれを見ることができます。 ... @DWinが示唆し、forceを最初に呼び出してください。

+1

私はループの使用が物事を複雑にすると思います。 'a < - " test "のようなものです。 AddFn(a); a < - "それは変わった"; l [[3]]() 'もポイントを取得します。 – Dason

+0

@Dason、大きな役割を果たすループについての正しいコメントの説明( '?"の ''?): 'for'"は、 'var'(この場合は' letter')を ' seq'(この場合は 'letters'、最後の要素は' z')です。 – BenBarnes

関連する問題