9.4 纯函数

优质
小牛编辑
134浏览
2023-12-01

如果一个函数的返回结果只取决于参数值,并且没有像修改参数、输出一些值等副作用,那么就可认为此函数是纯函数。

下面这个after函数就是一例。此函数比较两个Time变量并返回一个布尔值并指出第一个操作数是否比第二个晚:

bool after (Time& time1, Time& time2) {
    if (time1.hour > time2.hour) return true;
    if (time1.hour < time2.hour) return false;
    if (time1.minute > time2.minute) return true;
    if (time1.minute < time2.minute) return false;
    if (time1.second > time2.second) return true;
    return false;
}

当两个时间相等时,函数返回什么?函数是否有适当的返回值?如果是你为此函数编写文档,你会专门提及这种情况吗?

另外一例是addTime函数,负责计算两个时间值之和。比如现在是9:14:30,你的面包机工作时间是3小时35分钟,你可以使用addTime函数来计算什么时候面包做好。

下面是此函数的一个草稿,不一定完全正确:

Time addTime (Time& t1, Time& t2) {
    Time sum;
    sum.hour = t1.hour + t2.hour;
    sum.minute = t1.minute + t2.minute;
    sum.second = t1.second + t2.second;
    return sum;
}

下面举一个使用该函数的例子。若currentTime为当前时间,breadTime为面包机做面包用的总时间,你就可以用addTime计算面包做好的时间了。

Time currentTime = { 9, 14, 30.0 };
Time breadTime = { 3, 35, 0.0 };
Time doneTime = addTime (currentTime, breadTime);
printTime (doneTime);

这段程序的输出为12:49:30,答案正确。另外,还有些例子的结果是不正确的。你能想出一个吗?

这个函数的问题在于它没有处理秒数或分钟数加起来超过60的情况。这种情况我们必须将多出的秒数“进位”到分钟,或者多出的分钟进位到小时。

下面是再次修改函数后的正确版本:

Time addTime (Time& t1, Time& t2) {
    Time sum;
    sum.hour = t1.hour + t2.hour;
    sum.minute = t1.minute + t2.minute;
    sum.second = t1.second + t2.second;
    if (sum.second >= 60.0) {
        sum.second -= 60.0;
        sum.minute += 1;
    }
    if (sum.minute >= 60) {
        sum.minute -= 60;
        sum.hour += 1;
    }
    return sum;
}

代码正确了,但也变长了。稍后,我将给出另一个解决方案,能大大简短代码。

这段代码给出了我们之前没见过的两个操作符:+=和-=,用于简洁的表示变量的增减。比方说,语句

sum.second -= 60.0;

和语句

sum.second = sum.second - 60;

是等价的。