作者回复: 非常棒! 对于第 4 题,如果没有 delimiter 的,要返回剩余部分。可以看看我的参考答案: ```rust struct SentenceIter<'a> { s: &'a mut &'a str, delimiter: char, } impl<'a> SentenceIter<'a> { pub fn new(s: &'a mut &'a str, delimiter: char) -> Self { Self { s, delimiter } } } impl<'a> Iterator for SentenceIter<'a> { type Item = &'a str; fn next(&mut self) -> Option<Self::Item> { // 如果内部的字符串引用指向空,则提前结束 if self.s.is_empty() { return None; } match self.s.find(self.delimiter) { Some(pos) => { // 注意对于 utf8 char,取它的长度需要用 c.len_utf8() let len = self.delimiter.len_utf8(); let s = &self.s[..pos + len]; let suffix = &self.s[pos + len..]; // 更改内部字符串引用,指向剩余部分 *self.s = suffix; Some(s.trim()) } None => { // 没有找到句号时,有可能后续还有最后一句内容 let s = (*self.s).trim(); *self.s = ""; if s.len() == 0 { None } else { Some(s) } } } } } #[test] fn it_works() { let mut s = "This is the 1st sentence. This is the 2nd sentence."; let mut iter = SentenceIter::new(&mut s, '.'); assert_eq!(iter.next(), Some("This is the 1st sentence.")); assert_eq!(iter.next(), Some("This is the 2nd sentence.")); assert_eq!(iter.next(), None); } fn main() { let mut s = "a。 b。 c"; let sentences: Vec<_> = SentenceIter::new(&mut s, '。').collect(); println!("sentences: {:?}", sentences); } ``` playground:https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=4590211f7542553e7feef960e814ab0b
作者回复: 非常棒!1,2,3 答案正确!4 需要考虑最后的部分。对 main() 里的实例代码,这个只返回["a。", "b。"]。你可以看我之前在其他回答下的回复。 谢谢指正,对,trait object 那个图是有问题,ptr 应该指向 HtmlFormatter。有时候图 copy & paste 时,就回忘了把不用的部分删除并修改,lol。我回头让编辑更新!
作者回复: 不是 append 的关系。每一个 trait 和某个数据结构对该 trait 的实现都会生成一个静态的 vtable。vtable 是彼此独立的。 1. method call 不需要 table,通过类型就可以得到类型固定的 method call 的地址(编译期就可以完成了)。vtable 是一个运行期的概念。在 trait object 生成的时候,才指向具体的 vtable。 2. 你可以再仔细看看关于 vtable 的那几个图。并不是通过 addr + offset 来调 trait 的 method 的。是通过 vtable。比如一个 trait object 指向了 String Display 的 vtable,那么重这个 vtable 里就能找到 fmt 方法的地址。
作者回复: 因为 strtok 会修改传入的参数,使其指向 &str 的 tokenize 后面的位置,所以需要 &mut &str。你可以仔细看我画的图去理解。
作者回复: 👍
编辑回复: 恩是的,最好对编程语言相关基础概念有理解,这也是为什么“适合人群”中老师会标注掌握任意一门编程语言。另外,Rust基础语法,老师的想法是官方资料就很齐全了,大家可以配合学习
作者回复: 首先这里应该是 &dyn Bar,其次,Bar 是一个 trait,它的类型是不确定的,而 &T 是一个确定的类型,在编译时会根据使用编译成 Foo 或者其他类型。这是本质的区别。对于 trait,只能通过虚表来获得原始类型的能力和一些属性。
作者回复: 对,我是说指向 vtable 的指针是放在类结构里的。文中最后 summary 的图里也是这个意思吧?
作者回复: 1/2/3 正确。4 需要考虑 main() 中的场景,要处理不带 delimiter 的后续部分,可以看我之前的回答。 trait 泛型是对同一个数据结构你需要有多个不同的实现,trait 的关联类型是,在某个实现里,我需要设定和这个实现相关的类型。其实关联类型就和关联函数一样的。
作者回复: 谢谢!:)