0
点赞
收藏
分享

微信扫一扫

[Rust笔记] `?`操作符是如何“抽象”错误类型与“短路”函数的

?操作符是如何“抽象”错误类型与“短路”函数的

  • 首先,​​?​​​操作符是被用来勾连·函数体内​​Result<T, E1>​​​·与·函数返回值类型​​Result<T, E2>​​·的【语法糖】。它的“去糖”展开式如下:
  • [Rust笔记] `?`操作符是如何“抽象”错误类型与“短路”函数的_类型转换
  • 其次,就功能而言,​​?​​​操作符相当于“温和版”的​​Result::unwrap()​​成员方法。即,
  • 先将​​?​​​操作符前​​Result<T, E1>​​​中的​​E1​​​·类型转换·为【函数】返回值类型​​Result<T, E2>​​​中的​​E2​​。
  • 再“短路”当前执行函数和退出函数。注意:
  • 这一步要求​​E2​​​实现了​​From<E1> trait​​。
  • 这里是结束当前执行函数,而不像​​Result::unwrap()​​“粗暴”地结束当前执行线程。要不,怎么说​​?​​“温和”呢!
  • 若开启了​​Cargo.toml [package] panic = "abort"​​​,后者​​Result::unwrap()​​还会造成内存泄露。
  • 成功线 —— 取出​​?​​​操作符前​​Result<T, E1>​​​的内部值​​T​​和作为表达式的返回结果。
  • 失败线 ——
  • 接着,重点来了。【函数】返回值类型​​Result<T, E2>​​​中的​​E2​​是一个“同时兼容于所有其它错误类型的、统一的【“抽象”错误类型】”。按其“抽象”方式分为如下两种情况:


上面两种方式都能把·从函数体内抛出的·不同类型的·错误,经由​​?​​操作符,收拢于“一处”。

在这里,我把【类型转换】称为“抽象”是否有些牵强呀? 毕竟,其基础原理与​​oop​​中的【抽象】不太一样。



  • 前者的“一处”是(类型转换至)一个具体类型 —— 静态分派;
  • 后者的“一处”是(类型转换至)​​trait Object​​ —— 动态分派。
  • ​E2​​​就是​​Box<dyn Error>​​​,因为【标准库】给​​Box<T>​​​实现了​​From<Error> trait​​。其本质也是【类型转换】。
  • 这个,我一直以来使用得比较多。
  • ​E2​​​是实现了​​From<E1> trait​​​的任何具体类型。即,​​E1​​​可被类型转换为​​E2​​类型。【类型转换】是其底层机制。
  • 而且,不强制要求​​E2​​​再显示地实现​​Error trait​​。
  • 这一块是我曾经的知识盲点
  • 静态分派(抽象):[例程1]
  • 动态分派(抽象):[例程2]

  • 最后,借助于​​Option::ok_or(_)​​​或​​Option::ok_or_else(FnOnce)​​​,​​Option<T>​​​也能与​​?​​操作符搭配使用。即,[例程3]


  • 先将​​Option<T>​​​类型转换为​​Result<T, E>​

  • 再搭配​​?​​操作符语法糖




举报

相关推荐

0 条评论