我正在从The Rust Programming Language book available from No Starch Press学习Rust,但是遇到了一个问题,即编译器的行为与第4章第4章中的书中所解释的不一样。 77。
该书的第4章正在讨论所有权,第p页的示例。 77与此类似,但在var user_profile =[
{
"assessmentType":"FINAL",
"assessCatId":-1,
"assessReason":"2",
"assessAmount":"",
"assessTotal":null
},
{
"assessmentType":"FINAL",
"assessCatId":-1,
"assessReason":"2",
"assessTotal":null
},
{
"assessmentType":"FINAL",
"assessCatId":-1,
"assessReason":"",
"assessTotal":null
},
{
"assessmentType":"FINAL",
"assessCatId":0,
"assessReason":null,
"assessAmount":"",
"assessPenalty":"",
"assessTotal":0
},
{
"assessmentType":"FINAL",
"assessCatId":0,
"assessReason":null,
"assessTotal":null
},
{
"assessmentType":"FINAL",
"assessCatId":0,
"assessReason":"",
"assessTotal":null
},
{
"assessmentType":"FINAL",
"assessCatId":0,
"assessReason":"",
"assessTotal":null
},
{
"assessmentType":"FINAL",
"assessCatId":0,
"assessReason":"2075-09-09",
"assessAmount":"2075-09-17",
"assessTotal":null
},
{
"assessmentType":"FINAL",
"assessCatId":0,
"assessReason":"2075-09-09",
"assessTotal":null
},
{
"assessmentType":"FINAL",
"assessCatId":0,
"assessReason":"2075-09-17",
"assessTotal":null
},
{
"assessmentType":"FINAL",
"assessCatId":1,
"assessReason":"",
"assessAmount":"0",
"assessPenalty":"0",
"assessTotal":0
},
{
"assessmentType":"FINAL",
"assessCatId":2,
"assessReason":"",
"assessAmount":"0",
"assessPenalty":"0",
"assessTotal":0
},
{
"assessmentType":"FINAL",
"assessCatId":3,
"assessReason":"",
"assessAmount":"0",
"assessPenalty":"0",
"assessTotal":0
},
{
"assessmentType":"FINAL",
"assessCatId":1,
"assessReason":"A",
"assessAmount":"1",
"assessPenalty":"2",
"assessTotal":3
},
{
"assessmentType":"FINAL",
"assessCatId":2,
"assessReason":"B",
"assessAmount":"3",
"assessPenalty":"4",
"assessTotal":7
},
{
"assessmentType":"FINAL",
"assessCatId":3,
"assessReason":"C",
"assessAmount":"5",
"assessPenalty":"6",
"assessTotal":11
}
]
const output = user_profile.filter(({ assessCatId,assessReason }) => (assessCatId >= 1 && assessCatId <= 3) && assessReason);
console.log("here the outpuit is");
console.log(output);
中没有最后的println!()
(我也从第76页添加了注释和功能来创建MCVE)。 I also created a playground。
main()
我了解为什么编译器在当前位置会引发错误。但是我从书中了解到,当我尝试清除字符串时,它应该引起了编译器错误,因为我无法借用fn main() {
let mut s = String::from("Hello world!");
let word = first_word(&s);
// according to book, compiler should not allow this mutable borrow
// since I'm already borrowing as immutable, but it does allow it
s.clear();
// but of course I do get error here about immutable borrow later being
// used here, but shouldn't it have errored on the clear() operation before
// it got here?
println!("First word of s is \"{}\"", word);
}
// return string slice reference to first word in string or entire string if
// no space found
fn first_word(s: &String) -> &str {
let bytes = s.as_bytes();
for (i, &item) in bytes.iter().enumerate() {
if item == b' ' {
return &s[..i];
}
}
&s[..]
}
可变,因为它也借来不可变,因此消除了我收到错误的可能性(即,即使没有最后的s
,也不应编译)。但是,只要我不尝试在println!()
操作之后使用对word
的引用,它对我来说编译就很好。
该书使用的是Rust 1.21.0(请参阅第2页),而我使用的是Rust 1.31.0,因此这很可能是已引入编译器的更改,但我试图了解为什么。为什么现在比在书中指出会出错的地方更好地出错呢?
为清楚起见,我自己理解错误。我试图理解为什么它没有在书中所述的位置抛出编译器错误(即,为什么更改编译器行为?)。
答案 0 :(得分:5)
这是non-lexical lifetimes所做的更改,{{3}}是Rust最新版本的更新(如果我没记错的话,请参见Rust 1.31引入的2018版稳定)。
在Rust的早期版本(包括本书所基于的版本)中,任何引用都应该在创建它的整个范围内都有效(也就是说,直到括号括起来)。如果您使用word
删除了该行并尝试在旧版本上编译代码,则会产生相同的错误-“借来的是可变的,借来的是不可变的”。
现在,借阅检查器将跟踪引用是否真正被使用。如果您在word
之后没有使用s.clear()
,则可以假设在s
变成可变变量之前,可以安全地删除对s.clear()
的不变引用,因此您已经提到过,此代码将被安全地编译。在println!
处,借位检查器会看到不可变和可变借位的作用域是相交的,并确切地告诉您—请注意,错误分为三部分: