第六轮回 全局配置

第六轮回 全局配置

异教徒被囚禁于第六轮回的燃烧坟墓中.

一个全局配置可以通过”<<-“实现:

> x <- 1
> y <- 2
> fun
function () 
{
 x <- 101
 y <<- 102
}
> fun()
> x
[1] 1
> y
[1] 102  

但这就像是在火山口生活一样.

如果你需要使用“<<-“,请三思.如果你深思熟虑之后还是觉得需要使用“<<-“,请再三思.只有当你的老板因为你的不作为而生气的红了脸的时候,你也应该只是暂时性的使用“<<-“.早已经有提议(并非半开玩笑的)从R中消除“<<-“,但这并不意味着就清除了全局配置,只是强迫你使用assign()去实现相同的目的.

全局配置到底哪里错了呢? Surprise.

Surprise在电影和小说中是美好的.但是在程序中就不那么讨人喜欢了.

在R中,除了少数几个函数明确的有负作用(即对函数之外的环境造成影响)之外,其余的函数我们都期望是没有副作用的.函数中如果使用了全局配置,那就是与这种期望公然对抗.对于不熟悉这些代码的用户(甚至是几周前编写这些代码的作者),这里将会有一个变量在魔术般地变化.

全局配置的一个有用的(并不是极坏的)特殊场合是记忆.具体讲就是:程序的运行结果可以被存储起来,当后期再有相同的计算的时候,这个结果就可以仅仅从存储中找到而不是再次计算.全局配置在这种场合并不会令人担心,因为这个对用户并不可见.这也有一个命名销毁的问题–如果你在两个不同的函数中采用相同名字的变量去记忆结果,销毁就随之而来.

在R中,我们可以通过一个局部全局变量来实现记忆.(“局部全局”挺起来有点幽默,但是它却简洁地描述了到底是怎么一回事.)在下面计算斐波那契数列的例子中,我们使用了“<<-“,并且安全地使用.

fibonacci <- local({
                     memo <- c(1, 1, rep(NA, 100))
                     f <- function(x) 
                     {
                       if(x == 0) return(0)
                       if(x < 0) return(NA)
                       if(x > length(memo))
                       stop("'x' too big for implementation")
                       if(!is.na(memo[x])) return(memo[x])
                       ans <- f(x-2) + f(x-1)
                       memo[x] <<- ans
                       ans
                     }
                    })  

糊涂神是怎么说的?我们有一个仅仅通过“<<-“操作的本地化方式来实现记忆的函数.但是我们再该函数的本地环境中存放备忘记录.返回值就是大括号最后的那个值.当我们定义函数的时候一般不会对返回对象命名,但是在这种情况下我们需要命名因为这个函数需要递归调用.

现在我们玩玩看:

> 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努力去仅仅复制那些必须使用的对象,比如说当这个对象在函数里边发生变化的时候.这个轮回是大致概念上的正确,而非字里行间的正确.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值