Rust方法链式调用是否存在等价std::iter::inspect的中间值检查方法
Rust链式调用中间值检查方案
首先说明:你提到的孤儿规则限制其实不影响这类功能实现。你不能直接写impl<T> T为所有类型添加固有方法,这是Rust本身的语法限制,和孤儿规则无关。通过定义扩展trait的方式为所有类型实现通用方法是Rust的标准扩展模式,完全符合语法规则。
零依赖自实现
只需要在项目中添加如下几行代码,就能实现你需要的inspect功能。这个实现比你最初写的版本更灵活,同时支持所有权传递和引用链式调用,Release模式下会被编译器完全优化,没有额外开销:
trait Inspect { fn inspect<F: FnOnce(&Self)>(self, f: F) -> Self; } impl<T> Inspect for T { #[inline(always)] fn inspect<F: FnOnce(&Self)>(self, f: F) -> Self { f(&self); self } }
定义完成后,你示例中的调用代码就可以直接运行。
标准库快速调试方案
如果只是临时调试不想额外定义trait,直接使用内置的dbg!宏即可。dbg!会自动打印传入值的源码位置、Debug格式化内容,之后原样返回值的所有权,可以直接嵌入调用链。如果配合上面的Inspect trait使用写法非常简洁:
object .a() .inspect(|x| dbg!(x)) .b() .inspect(|x| dbg!(x)) .c();
临时调试也可以直接用括号包裹表达式,不需要额外定义:
(dbg!(object.a())).b()
生态成熟实现
Rust生态中已经有专门做这类管道操作的成熟库tap,属于广泛使用的零开销工具库,提供了完整的链式操作能力,完全匹配你的需求:
tap:接收不可变引用闭包,执行检查逻辑后返回原值,等价于你需要的inspect方法tap_mut:接收可变引用闭包,支持在链式调用过程中临时修改中间值pipe:接收值的所有权,返回闭包执行结果,用于链式值转换
使用时引入对应trait即可直接调用:
use tap::Tap; object .a() .tap(|x| println!("after a(): {:?}", x)) .b() .tap(|x| println!("after b(): {:?}", x)) .c();
内容的提问来源于stack exchange,提问作者BallpointBen
相关产品推荐
相关产品推荐

