23|类型系统:如何在实战中使用泛型编程?
该思维导图由 AI 生成,仅供参考
泛型数据结构的逐步约束
- 深入了解
- 翻译
- 解释
- 总结
Rust中泛型编程的实际应用是必不可少的技能。本文深入探讨了如何在实践中运用泛型参数以及其三种常见使用场景。首先,通过对标准库中的BufReader结构的泛型参数使用进行了详细讲解,展示了如何在定义和实现数据结构时使用泛型参数来延迟决策。接着,作者介绍了泛型参数的三种使用场景:延迟数据结构的绑定、声明数据结构中不直接使用但在实现过程中需要用到的类型、以及让同一个数据结构对同一个trait可以拥有不同的实现。此外,文章还介绍了如何使用PhantomData来处理在定义数据结构时暂时不需要但在实现过程中需要的泛型参数,以及如何在编译期做状态的检测,避免运行期检测的负担和潜在的错误。文章还通过实例展示了泛型函数的高级技巧,包括返回值携带泛型参数和处理复杂的泛型参数。总的来说,本文深入浅出地介绍了泛型编程在实战中的应用及其重要性,对读者快速了解Rust中泛型编程的实际应用具有指导意义。文章强调了泛型编程在Rust开发中的重要性,提供了丰富的实例和技巧,帮助读者更好地理解和应用泛型编程。
《陈天 · Rust 编程第一课》,新⼈⾸单¥68
全部留言(9)
- 最新
- 精选
- 罗杰impl Iterator for Equation<Quadratic> 判断返回 None 的地方是不是应该写成 `if self.current >= u16::MAX as u32`,不然会有逻辑错误。
作者回复: 👍 是的,非常厉害!这个 bug 我也是又看了一遍代码才发现。
2021-10-2012 - Marvichov和老师的对应下... 1. 使用泛型参数延迟数据结构的绑定; 2. 使用泛型参数和 PhantomData,声明数据结构中不直接使用,但在实现过程中需要用到的类型 3. 使用泛型参数让同一个数据结构对同一个 trait 可以拥有不同的实现。 1. 面向interface编程; 只不过静态多态 2. 引入自由参数 -> 大部分impl共享; 剩下的, 根据自由参数类型的不同做template specialization -> 比如tag struct -> 本质还是代码共享 3. NewTypePattern; 一套代码给多个不同的type共用; 这个blog里面的例子比较生动: https://www.greyblake.com/blog/2021-10-11-phantom-types-in-rust/; golang里面也经常用kilometer, mile来做例子, 类似于`type mile i32`;
作者回复: 👍
2021-10-187 - MarvichovCpp里面用tag和多generic param的例子也很多… 比如Cpp的iterator, 多个泛型做参数, 不需要PhantomData; template< class Category, // tag data, 类似于 AsyncProstReader D class T, class Distance = std::ptrdiff_t, class Pointer = T*, class Reference = T& > struct iterator; 所以, 感觉PhantomData的主要用途是compile time ownership check; 我的疑问也就主要集中在ownership... 问题1: from PhantomData doc: > Adding a PhantomData field to your type tells the compiler that your type acts as though it stores a value of type T, even though it doesn’t really. 不太明白, 为啥需要ownership. 比如AsyncProstReader的T是约束R的return type的, 按理说不用own T; 而且into和dest member全程没被调用过 /// A wrapper around an async reader that produces an asynchronous stream of prost-decoded values #[derive(Debug)] pub struct AsyncProstReader<R, T, D> { reader: R, pub(crate) buffer: BytesMut, into: PhantomData<T>, dest: PhantomData<D>, } 如果不需要对T, D的ownership, 为啥不来个`PhantomDataNotOwned`来满足这样的场景: 不需要ownership, 但是这个generic type T不是多余的呢? ---- 问题2: > This information is used when computing certain safety properties. 这句目前理解不了…假设对T有ownership, 没看出有啥特殊的safety需求
作者回复: 我的理解是大部分时候 PhantomData 跟其它语言的 Phantom Type 是一个作用,为数据结构提供声明时没用用到,但在实现时需要用到的类型。因为这里你实实在在就只用 T 来保证类型的正确性,并没有涉及到 owership。 但在有些场合下,比如 Unique<T>,这里,如果没用 PhantomData<T>的话,你想想 Unique<T> 是否 own T?并不 own,因为 pointer 是一个指针类型,所以从类型上,Unique<T> 不 own T,但这里 Unique<T> 应该 own T 才对。所以 Rust 使用 PhantomData 来表述这个作用,见:https://github.com/rust-lang/rfcs/blob/master/text/0769-sound-generic-drop.md#phantom-data ```Rust pub struct Unique<T: ?Sized> { pointer: *const T, _marker: PhantomData<T>, } ``` 这属于 PhantomData 的高级用法,大部分时候我们用类型系统解决问题需要使用 PhantomData 时,都是大家在其他语言中惯常的用法,所以我没有提这个 owership 的用法。
2021-10-1824 - Quincy1. 参数 F 是一个闭包,接收 Self::Item,返回 Fut 类型; 2. 参数 Fut 是一个 Future<Output=()>; 所以 f 是一个闭包接收 Self::Item 闭包的返回值是 Future<Output=()> 使用参考源代码: ```rust .for_each_concurrent( /* limit */ 2, |rx| async move { rx.await.unwrap(); } ) ```
作者回复: 👍
2021-10-28 - 渡鸦10086关于思考题: f 是一个闭包,以 `Self::Item` 类型作为输入,以一个实现了 `Future` trait 的类型 Fut 作为输出,其中`Future` 的关联类型 `Output` 是 unit 类型2022-01-162
- Geek_7c0961老师现在implement trait 用在返回值的类型了,那么 trait obejct还有什么用处么?它的性能那么差. https://doc.rust-lang.org/rust-by-example/trait/impl_trait.html2022-05-161
- A.Y.关于第三点使用场景,似乎可以用于替代其他面向对象语言中有而rust不支持的类继承。2022-05-071
- 🐲礁sir终于明白substrate的frame/executiv/src/lib.rs里面这段代码的用意:2022-09-11归属地:四川1
- zahiphantom type 的例子,感觉像java中的继承。2022-08-14归属地:北京