[英]Rustlings Exercise Traits2, Implement Trait on Vec
The exercise requires me to Implement the trait to Vec.该练习要求我将特征实现到 Vec。 The tests are there and they are failing, which is a good place to start.测试就在那里,但它们都失败了,这是一个很好的起点。 I've done the trait implementation for the String and it was easy, Vec is another story.我已经完成了 String 的 trait 实现,这很简单,Vec 是另一回事。 I'm not sure what the method needs to return, it fails on various returns.我不确定该方法需要返回什么,它在各种返回时都失败了。 I'm providing original code, my attempt and the errors i get for my atempt.我正在提供原始代码、我的尝试以及我尝试时遇到的错误。 Hopefull that will be enough.希望这就足够了。
Original Code from the Rustlings repo : Rustlings 仓库的原始代码:
// traits2.rs
//
// Your task is to implement the trait
// `AppendBar' for a vector of strings.
//
// To implement this trait, consider for
// a moment what it means to 'append "Bar"'
// to a vector of strings.
//
// No boiler plate code this time,
// you can do this!
// I AM NOT DONE
trait AppendBar {
fn append_bar(self) -> Self;
}
//TODO: Add your code here
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn is_vec_pop_eq_bar() {
let mut foo = vec![String::from("Foo")].append_bar();
assert_eq!(foo.pop().unwrap(), String::from("Bar"));
assert_eq!(foo.pop().unwrap(), String::from("Foo"));
}
}
and my attempt to solve it:我试图解决它:
// traits2.rs
//
// Your task is to implement the trait
// `AppendBar' for a vector of strings.
//
// To implement this trait, consider for
// a moment what it means to 'append "Bar"'
// to a vector of strings.
//
// No boiler plate code this time,
// you can do this!
// I AM NOT DONE
use std::clone::Clone;
trait AppendBar {
fn append_bar(&mut self) -> Self;
}
//TODO: Add your code here
impl<T: Clone> AppendBar for Vec<T> {
fn append_bar(&mut self) -> Self {
let bar: T = String::from("Bar");
self.to_vec().push(bar)
// self.to_vec()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn is_vec_pop_eq_bar() {
let mut foo = vec![String::from("Foo")].append_bar();
assert_eq!(foo, vec![String::from("Foo"), String::from("Bar")]);
assert_eq!(foo.pop().unwrap(), String::from("Bar"));
assert_eq!(foo.pop().unwrap(), String::from("Foo"));
}
}
Which compiles to an Error :编译为错误:
! Compiling of exercises/traits/traits2.rs failed! Please try again. Here's the output:
error[E0308]: mismatched types
--> exercises/traits/traits2.rs:22:22
|
20 | impl<T: Clone> AppendBar for Vec<T> {
| - this type parameter
21 | fn append_bar(&mut self) -> Self {
22 | let bar: T = String::from("Bar");
| - ^^^^^^^^^^^^^^^^^^^ expected type parameter `T`, found struct `std::string::String`
| |
| expected due to this
|
= note: expected type parameter `T`
found struct `std::string::String`
= help: type parameters must be constrained to match other types
= note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters
error[E0308]: mismatched types
--> exercises/traits/traits2.rs:23:9
|
21 | fn append_bar(&mut self) -> Self {
| ---- expected `std::vec::Vec<T>` because of return type
22 | let bar: T = String::from("Bar");
23 | self.to_vec().push(bar)
| ^^^^^^^^^^^^^^^^^^^^^^^ expected struct `std::vec::Vec`, found `()`
|
= note: expected struct `std::vec::Vec<T>`
found unit type `()`
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0308`.
I've read and re-read the suggested part and the traits in the book but it's beyond me.我已经阅读并重新阅读了书中建议的部分和特征,但它超出了我的范围。 I'm sure it's a simple solution to it but i can't see it.我确定这是一个简单的解决方案,但我看不到它。
There's a discrepancy to Aloso's answer. Aloso 的回答有出入。 Andre gives it too.安德烈也给了。
When you take in self
:当你接受self
:
fn append_bar(self) -> Self {
self.push("Bar".to_owned());
self
}
You are taking in a mutable Vec
:你正在接受一个可变的Vec
:
let mut foo = vec![String::from("Foo")].append_bar();
assert_eq!(foo.pop().unwrap(), String::from("Bar"));
assert_eq!(foo.pop().unwrap(), String::from("Foo"));
Even though the Variable foo
is declared to be mutable, the method append_bar()
takes in a immutable variable.即使变量foo
被声明为可变的,方法append_bar()
接受一个不可变的变量。 You don't need to borrow self
because you're not trying to take full ownership, you're trying to modify the existing data residing in said variable.您不需要借用self
因为您不是试图获得全部所有权,而是试图修改驻留在所述变量中的现有数据。 The correct answer is正确答案是
fn append_bar(mut self) -> Self {
self.push("Bar".to_owned()); // || .to_string() || String::from("Bar")
// Whatever gets the point across. As the String literal is essentially a "Borrowed" string.
self
}
Within the scope of append_bar()
you're trying to mutate the collection of String
s and return it with the appended string.在append_bar()
的范围内,您试图改变String
的集合并将其与附加的字符串一起返回。
There are several issues:有几个问题:
String
to generic Vec<T>
, where T
can be any type!您尝试将String
推送到泛型Vec<T>
,其中T
可以是任何类型!fn append_bar(&mut self) -> Self
but it should be但应该是fn append_bar(self) -> Self
Vec::push
, but this method doesn't return anything.您尝试返回Vec::push
的结果,但此方法不返回任何内容。 To fix the first issue, implement the trait for Vec<String>
instead of Vec<T>
.要解决第一个问题,请为Vec<String>
而不是Vec<T>
。 That's what the assignment is asking for:这就是作业要求的内容:
// Your task is to implement the trait // `AppendBar' for a vector of strings.
To fix the second issue, you have to remove the &
, so the method accepts an owned value.要解决第二个问题,您必须删除&
,因此该方法接受一个拥有的值。
To fix the last issue, return self
after calling Vec::push
in a separate statement:要解决最后一个问题,请在单独的语句中调用Vec::push
后返回self
:
self.push(bar);
self
Thanks to @Aloso for help and Jussi too i managed to get the example working.感谢@Aloso 和 Jussi 的帮助,我设法使示例正常工作。
Mutation was needed in order to compile, so i ended up with code that compiles as follows:为了编译需要突变,所以我最终得到了编译如下的代码:
// traits2.rs
//
// Your task is to implement the trait
// `AppendBar' for a vector of strings.
//
// To implement this trait, consider for
// a moment what it means to 'append "Bar"'
// to a vector of strings.
//
// No boiler plate code this time,
// you can do this!
// I AM NOT DONE
trait AppendBar {
fn append_bar(&mut self) -> Self;
}
//TODO: Add your code here
impl AppendBar for Vec<String> {
fn append_bar(&mut self) -> Self {
self.push(String::from("Bar"));
self.to_vec()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn is_vec_pop_eq_bar() {
let mut foo = vec![String::from("Foo")].append_bar();
assert_eq!(foo, vec![String::from("Foo"), String::from("Bar")]);
assert_eq!(foo.pop().unwrap(), String::from("Bar"));
assert_eq!(foo.pop().unwrap(), String::from("Foo"));
}
}
I believe the correct answer for this problem shall look like this:我相信这个问题的正确答案应该是这样的:
trait AppendBar {
fn append_bar(self) -> Self;
}
impl AppendBar for Vec<String> {
fn append_bar(mut self) -> Self {
self.push("Bar".to_string());
self
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.