異教徒被囚禁於第六輪迴的燃燒墳墓中.
乙個全域性配置可以通過」<<-「實現:
> x <- 1
> y <- 2
> fun
function ()
> fun()
> x
[1] 1
> y
[1] 102
但這就像是在火山口生活一樣.
如果你需要使用「<<-「,請三思.如果你深思熟慮之後還是覺得需要使用「<<-「,請再三思.只有當你的老闆因為你的不作為而生氣的紅了臉的時候,你也應該只是暫時性的使用「<<-「.早已經有提議(並非半開玩笑的)從r中消除「<<-「,但這並不意味著就清除了全域性配置,只是強迫你使用assign()去實現相同的目的.
全域性配置到底**錯了呢? surprise.
surprise在電影和**中是美好的.但是在程式中就不那麼討人喜歡了.
在r中,除了少數幾個函式明確的有負作用(即對函式之外的環境造成影響)之外,其餘的函式我們都期望是沒有***的.函式中如果使用了全域性配置,那就是與這種期望公然對抗.對於不熟悉這些**的使用者(甚至是幾周前編寫這些**的作者),這裡將會有乙個變數在魔術般地變化.
全域性配置的乙個有用的(並不是極壞的)特殊場合是記憶.具體講就是:程式的執行結果可以被儲存起來,當後期再有相同的計算的時候,這個結果就可以僅僅從儲存中找到而不是再次計算.全域性配置在這種場合並不會令人擔心,因為這個對使用者並不可見.這也有乙個命名銷毀的問題–如果你在兩個不同的函式中採用相同名字的變數去記憶結果,銷毀就隨之而來.
在r中,我們可以通過乙個區域性全域性變數來實現記憶.(「區域性全域性」挺起來有點幽默,但是它卻簡潔地描述了到底是怎麼一回事.)在下面計算斐波那契數列的例子中,我們使用了「<<-「,並且安全地使用.
fibonacci <- local(
})
糊塗神是怎麼說的?我們有乙個僅僅通過「<<-「操作的本地化方式來實現記憶的函式.但是我們再該函式的本地環境中存放備忘記錄.返回值就是大括號最後的那個值.當我們定義函式的時候一般不會對返回物件命名,但是在這種情況下我們需要命名因為這個函式需要遞迴呼叫.
現在我們玩玩看:
> fibonacci(4)
[1] 3
> head(get(』memo』, envir=environment(fibonacci)))
[1] 1 1 2 3 na na
通過計算入參是4的fibonacci(),memo的第三個和第四個函式被填充進來.這些值將不會被重複計算,需要用的時候僅僅是查表就可以了.
r總是進行著值傳遞.它從不會進行引用傳遞.
在r中有兩種人:一種是理解上邊所我所說的,一種不是.
如果你不理解這些的話,r是很適合你的–意思是r對你來說是安全的(儘管本章都在說一些相反的話題).f翻譯**話就是說在r中讓資料」腐爛」是極度困難的.畢竟智者知無止境.
如果你真的知道這一輪迴我們所討論的問題,那麼你或許早就領悟到了r是深受函式式程式設計影響的–負作用被降到最低.或許你會擔心這預示著記憶體的嚴重低效使用.好吧,這輪迴我們討論的問題就是乙個謊言.如果這只是字面上的正確,當物件(或許非常大)是函式入參時總會被複製.事實上,r努力去僅僅複製那些必須使用的物件,比如說當這個物件在函式裡邊發生變化的時候.這個輪迴是大致概念上的正確,而非字裡行間的正確.