函数引用透明性(referential transparency)

1. 基础

初学程序设计时,比较容易混淆的两个概念是数学函数(math function)和程序中使用的函数。

在数学函数中 y=f(x)y=f(x),一个输入值有固定的输出值。例如,无论计算多少次,sinπsin⁡π 的结果总是 0。如果 f(x)=x/2f(x)=x/2,那么 f(10)f(10) 无论计算 100 次还是 1000 次,其结果都是 5.

程序设计中的函数却不具备这种稳定的特性,因为函数的执行不仅依赖于输入值,而且会受到全局变量输入文件类的成员变量等诸多因素的影响。如下:

int counter = 0;
int count(){
    return ++counter;
}

此函数输入没有输入值,但每次都返回不同的结果。当然,就像数学函数那样,程序中函数还可以设计成“对同一输入值每次都返回相同结果”的形式。
函数的返回值只依赖于其输入值,这种特性就称为引用透明性(referential transparency)

2. 动态规划的缓存

显然,动态规划所使用的制表法(也即缓存)只能应用于具有引用透明性的函数。如果外在因素使相同输入值返回不同结果值,则不能缓存。

也即缓存对应的 map,实现的是同一个输入(key),同一个输出(value),而不可能出现同一个输入,可以得到不同的输出,也即输出结果的不确定性。

3 Scala纯函数

对于scala的并行容器 所使用的方法中(运算子),只要它们的运算子是纯函数,那么结果将是确定的。
纯函数指的是给定相同输入总是得到相同输出的函数,即没有任何副作用。
比如,函数(x: Int) => x + 1是纯函数。而下面的函数则不是纯函数,因为它修改了uid值的状态。

 val uid = new AtomicInteger(0)
 val f = (x: Int) => (x, uid.incrementAndGet())

即使一个函数没有修改任何内存位置,如果它读取的内存位置有可能发生变化,那它也不是纯函数。比如,下面的函数g就不是纯函数。

val g = (x: Int) => (x, uid.get)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值