如下面的代码所示,我想封装一个计时函数,它返回闭包的结果和执行时间。
use tap::prelude::Pipe;
use std::time::{Instant, Duration};
pub fn measure_time_with_value<T>(f: impl FnOnce() -> T) -> (T, Duration) {
Instant::now().pipe(|s| (f(), s)).pipe(|(f, s)| (f, s.elapsed()))
}
但是我不知道元组参数的执行顺序是否从左到右,也就是是否可以简化为下面的代码:
pub fn measure_time_with_value<T>(f: impl FnOnce() -> T) -> (T, Duration) {
Instant::now().pipe(|s| (f(), s.elapsed()))
}
来自Rust参考,章节"表达式",小节"操作数的求值顺序";(我加亮):
操作数求值顺序
下面的表达式列表都以相同的方式计算其操作数,如列表后面所述。其他表达式要么不接受操作数,要么按照各自页面的描述有条件地求值。
<
- 废弃表达式/gh>错误传播表达式
<- 否定表达/gh>
- 算术和逻辑二进制运算符
- 比较运算符
- 类型转换表达式
<- 分组表达式/gh><
- 数组表达/gh><
- 等待表达式/gh><
- 索引表达式/gh><
- 元组表达/strong>
元组索引表达式<- 结构表达式/gh><
- 调用表达式/gh>方法调用表达式
<- 字段表达式/gh><
- 打破表达式/gh><
- 范围表达式/gh><
- 返回表达式/gh>
这些表达式的操作数在应用表达式的效果之前求值。包含多个操作数的表达式从左到右求值如源代码所示。
[…]
例如,两个next方法调用将始终以相同的顺序调用:
let mut one_two = vec![1, 2].into_iter(); assert_eq!( (1, 2), (one_two.next().unwrap(), one_two.next().unwrap()) );
所以,是的,由于元组表达式的求值保证从左到右,您的代码可以按照您描述的方式简化。