我正在尝试使用Rust书和Exercism.io网站学习Rust。 我对this specific exercise有疑问。代码如下:
pub fn series(_digits: &str, _len: usize) -> Vec<String> {
(0.._digits.len() + 1 - _len)
.map(|i| _digits[i..i + _len].to_string())
.collect()
}
例如,series("12345", 3)
应该返回包含Vec
的{{1}}。
我使用["123", "234", "345"]
代替了(0.._digits.len() + 1 - _len)
,但是在这种情况下,单元测试“ test_too_long”失败了:
(0.._digits.len() - _len + 1)
我很惊讶,因为看起来对我来说是一样的。为什么失败了?
答案 0 :(得分:1)
之所以会发生这种情况,是因为在调试模式下,本来会因恐慌而溢出的算术运算和恐慌导致测试失败。
使用重新排列的版本(playground),在series("12345", 6)
中,digits.len() - len + 1
变成5usize - 6usize + 1usize
。该程序甚至没有进入+ 1
,因为只有5usize - 6usize
恐慌。 (usize
不能代表负数,因此从6
中减去5
会导致溢出。)
错误消息强烈暗示了故障的性质:
---- test_too_long stdout ----
thread 'test_too_long' panicked at 'attempt to subtract with overflow', src/lib.rs:2:9
note: Run with `RUST_BACKTRACE=1` for a backtrace.
digits.len() + 1 - len
可以工作,因为6
比字符串的长度精确 一倍,因此5 + 1 - 6
可以求值为零而不会溢出。但是,如果您将test_too_long
改为调用series("12345", 7)
,则两个版本都会出现故障。这似乎是编写测试套件的任何人的疏忽,尤其是考虑到说明未指定预期行为的情况:
如果您要求从5位数字的字符串中获取6位数字的序列,那么您应得到的一切都应该得到。
对于它的价值,这是一种使series
返回大于输入长度的len
的空向量的一种方法:(digits.len() + 1).saturating_sub(len)
就像digits.len() + 1 - len
,但是如果相减的结果小于0
,它只会返回0
。