前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >【译文】Rust组合器

【译文】Rust组合器

作者头像
袁承兴
发布于 2021-01-14 02:35:57
发布于 2021-01-14 02:35:57
65700
代码可运行
举报
运行总次数:0
代码可运行

Combinator

原文:Learning Rust Error Handling Combinators

什么是组合器?

  • “组合器”有一种非正式的含义,指的是组合器模式,一种以组合事物为中心思想来组织库的方式。通常,会有个类型T,一些用于构造T类型“原”值的函数,以及一些“组合器”,它们可以通过各种方式组合T类型的值建立更复杂的T类型的值。另一个定义是没有自变量的函数。 __ wiki.haskell.org
  • 组合器是一个从程序片段构建程序片段的函数;从某种意义上说,使用组合器的程序员自动化地构造很多所需的程序,而不是手工编写每个细节。 __ John Hughes—Generalizing Monads to Arrows via Functional Programming Concepts

Rust生态系统中“组合器”的确切定义还不太清晰。

  • or(), and(), or_else(), and_then()
  • **组合两个类型为T 的值并返回相同的类型T **。
  • filter() for Option types
  • **使用闭包作为条件函数过滤类型T **。
  • 返回相同的类型T
  • map(), map_err()
  • 通过闭包转换类型T.
  • 可以更改T中值的数据类型。 例如 Some<&str> 转换为 Some<usize> 或者 Err<&str> to Err<isize> 等。
  • map_or(), map_or_else()
  • 通过应用闭包来转换T类型,并返回T类型内部的值
  • 对于 NoneErr,需要一个默认值或者一个闭包
  • ok_or(), ok_or_else() for Option types
  • Option 转为 Result .
  • as_ref(), as_mut()
  • 将类型T转换为引用或可变引用

or()和and()

组合两个返回值为Option/Result的表达式

  • or():如果其中一个得到了SomeOk,该值将立即返回。
  • and():如果两个都获得SomeOk,则返回第二个表达式的值。如果其中一个为NoneErr,则该值立即返回。
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
fn main() {
  let s1 = Some("some1");
  let s2 = Some("some2");
  let n: Option<&str> = None;let o1: Result<&str, &str> = Ok("ok1");
  let o2: Result<&str, &str> = Ok("ok2");
  let e1: Result<&str, &str> = Err("error1");
  let e2: Result<&str, &str> = Err("error2");
​
  assert_eq!(s1.or(s2), s1); // Some1 or Some2 = Some1
  assert_eq!(s1.or(n), s1);  // Some or None = Some
  assert_eq!(n.or(s1), s1);  // None or Some = Some
  assert_eq!(n.or(n), n);    // None1 or None2 = None2
​
  assert_eq!(o1.or(o2), o1); // Ok1 or Ok2 = Ok1
  assert_eq!(o1.or(e1), o1); // Ok or Err = Ok
  assert_eq!(e1.or(o1), o1); // Err or Ok = Ok
  assert_eq!(e1.or(e2), e2); // Err1 or Err2 = Err2
​
  assert_eq!(s1.and(s2), s2); // Some1 and Some2 = Some2
  assert_eq!(s1.and(n), n);   // Some and None = None
  assert_eq!(n.and(s1), n);   // None and Some = None
  assert_eq!(n.and(n), n);    // None1 and None2 = None1
​
  assert_eq!(o1.and(o2), o2); // Ok1 and Ok2 = Ok2
  assert_eq!(o1.and(e1), e1); // Ok and Err = Err
  assert_eq!(e1.and(o1), e1); // Err and Ok = Err
  assert_eq!(e1.and(e2), e1); // Err1 and Err2 = Err1
}

Rust nightly支持Option类型的xor(),它仅在一个表达式获得Some时才返回Some,但两个则不然。

or_else()

类似于or()。唯一的区别是,第二个表达式应是一个返回相同类型T的闭包。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
fn main() {
    // or_else with Option
    let s1 = Some("some1");
    let s2 = Some("some2");
    let fn_some = || Some("some2"); // similar to: let fn_some = || -> Option<&str> { Some("some2") };let n: Option<&str> = None;
    let fn_none = || None;
​
    assert_eq!(s1.or_else(fn_some), s1);  // Some1 or_else Some2 = Some1
    assert_eq!(s1.or_else(fn_none), s1);  // Some or_else None = Some
    assert_eq!(n.or_else(fn_some), s2);   // None or_else Some = Some
    assert_eq!(n.or_else(fn_none), None); // None1 or_else None2 = None2// or_else with Result
    let o1: Result<&str, &str> = Ok("ok1");
    let o2: Result<&str, &str> = Ok("ok2");
    let fn_ok = |_| Ok("ok2"); // similar to: let fn_ok = |_| -> Result<&str, &str> { Ok("ok2") };let e1: Result<&str, &str> = Err("error1");
    let e2: Result<&str, &str> = Err("error2");
    let fn_err = |_| Err("error2");
​
    assert_eq!(o1.or_else(fn_ok), o1);  // Ok1 or_else Ok2 = Ok1
    assert_eq!(o1.or_else(fn_err), o1); // Ok or_else Err = Ok
    assert_eq!(e1.or_else(fn_ok), o2);  // Err or_else Ok = Ok
    assert_eq!(e1.or_else(fn_err), e2); // Err1 or_else Err2 = Err2
}

and_then()

and()类似。唯一的区别是,第二个表达式应是一个返回相同类型T的闭包。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
fn main() {
    // and_then with Option
    let s1 = Some("some1");
    let s2 = Some("some2");
    let fn_some = |_| Some("some2"); // similar to: let fn_some = |_| -> Option<&str> { Some("some2") };let n: Option<&str> = None;
    let fn_none = |_| None;
​
    assert_eq!(s1.and_then(fn_some), s2); // Some1 and_then Some2 = Some2
    assert_eq!(s1.and_then(fn_none), n);  // Some and_then None = None
    assert_eq!(n.and_then(fn_some), n);   // None and_then Some = None
    assert_eq!(n.and_then(fn_none), n);   // None1 and_then None2 = None1// and_then with Result
    let o1: Result<&str, &str> = Ok("ok1");
    let o2: Result<&str, &str> = Ok("ok2");
    let fn_ok = |_| Ok("ok2"); // similar to: let fn_ok = |_| -> Result<&str, &str> { Ok("ok2") };let e1: Result<&str, &str> = Err("error1");
    let e2: Result<&str, &str> = Err("error2");
    let fn_err = |_| Err("error2");
​
    assert_eq!(o1.and_then(fn_ok), o2);  // Ok1 and_then Ok2 = Ok2
    assert_eq!(o1.and_then(fn_err), e2); // Ok and_then Err = Err
    assert_eq!(e1.and_then(fn_ok), e1);  // Err and_then Ok = Err
    assert_eq!(e1.and_then(fn_err), e1); // Err1 and_then Err2 = Err1
}

filter()

通常,在编程语言中,filter函数与数组或迭代器配合使用,通过在函数/闭包中过滤自身的元素来创建新的数组/迭代器。 Rust也提供了filter()作为迭代器的适配器,以便在迭代器的每个元素上应用闭包,以将其转换为另一个迭代器。但是,在这里我们讨论的是Option类型的filter()的函数。

当我们传递Some值并且给定的闭包基于该值返回true时,才会返回相同的Some类型。如果传递None类型或闭包返回false,则返回None。闭包使用Some中的值作为参数。 而且,Rust仅支持Option类型的filter()

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
fn main() {
    let s1 = Some(3);
    let s2 = Some(6);
    let n = None;let fn_is_even = |x: &i8| x % 2 == 0;
​
    assert_eq!(s1.filter(fn_is_even), n);  // Some(3) -> 3 is not even -> None
    assert_eq!(s2.filter(fn_is_even), s2); // Some(6) -> 6 is even -> Some(6)
    assert_eq!(n.filter(fn_is_even), n);   // None -> no value -> None
}

map() and map_err()

通常,在编程语言中,map()函数与数组或迭代器配合使用,以对数组或迭代器的每个元素应用闭包。 Rust也提供了map()作为迭代器的适配器,以便在迭代器的每个元素上应用闭包,以将其转换为另一个迭代器。但是,在这里我们讨论的是Option和Result类型的map()的函数。

  • map():通过应用闭包转换类型T。 SomeOk块的数据类型可以根据闭包的返回类型进行更改。将Option<T>转换为Option<U>Result<T, E>转换为Result <U, E>

⭐ 通过map(),只有SomeOk的值被改变。不会影响Err内部的值(None根本不包含任何值)。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
fn main() {
    let s1 = Some("abcde");
    let s2 = Some(5);let n1: Option<&str> = None;
    let n2: Option<usize> = None;let o1: Result<&str, &str> = Ok("abcde");
    let o2: Result<usize, &str> = Ok(5);let e1: Result<&str, &str> = Err("abcde");
    let e2: Result<usize, &str> = Err("abcde");let fn_character_count = |s: &str| s.chars().count();
​
    assert_eq!(s1.map(fn_character_count), s2); // Some1 map = Some2
    assert_eq!(n1.map(fn_character_count), n2); // None1 map = None2
​
    assert_eq!(o1.map(fn_character_count), o2); // Ok1 map = Ok2
    assert_eq!(e1.map(fn_character_count), e2); // Err1 map = Err2
}
  • Result类型的map_err():可以根据闭包的返回类型来更改Err块的数据类型。将Result <T, E>转换为Result <T, F>

⭐ 通过map_err(),只有Err值被改变。不会影响Ok内部的值。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
fn main() {
    let o1: Result<&str, &str> = Ok("abcde");
    let o2: Result<&str, isize> = Ok("abcde");let e1: Result<&str, &str> = Err("404");
    let e2: Result<&str, isize> = Err(404);let fn_character_count = |s: &str| -> isize { s.parse().unwrap() }; // convert str to isize
​
    assert_eq!(o1.map_err(fn_character_count), o2); // Ok1 map = Ok2
    assert_eq!(e1.map_err(fn_character_count), e2); // Err1 map = Err2
}

map_or() and map_or_else()

希望您还记得unwrap_or()unwrap_or_else()函数的功能。这些函数有相似之处。但是map_or()map_or_else()SomeOk值应用闭包,并返回类型T中的值。

  • map_or():仅支持Option类型(不支持Result)。将闭包应用于Some中的值,然后根据闭包返回输出。对于None将返回给定的默认值。
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
fn main() {
    const V_DEFAULT: i8 = 1;let s = Some(10);
    let n: Option<i8> = None;
    let fn_closure = |v: i8| v + 2;
​
    assert_eq!(s.map_or(V_DEFAULT, fn_closure), 12);
    assert_eq!(n.map_or(V_DEFAULT, fn_closure), V_DEFAULT);
}
  • map_or_else():支持Option类型和Results类型(Result还在nightly)。与map_or()类似,但要对于第一个参数,要提供另一个闭包,而不是默认值。

None不包含任何值。因此,对于Option类型,无需输入参数传递给闭包。但是Err类型中包含值。因此,在使用过程中,对于Result类型,默认闭包应该能读取输入。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#![feature(result_map_or_else)] // enable unstable library feature 'result_map_or_else' on nightly
fn main() {
    let s = Some(10);
    let n: Option<i8> = None;let fn_closure = |v: i8| v + 2;
    let fn_default = || 1; // None doesn't contain any value. So no need to pass anything to closure as input.
​
    assert_eq!(s.map_or_else(fn_default, fn_closure), 12);
    assert_eq!(n.map_or_else(fn_default, fn_closure), 1);let o = Ok(10);
    let e = Err(5);
    let fn_default_for_result = |v: i8| v + 1; // Err contain some value inside it. So default closure should able to read it as input
​
    assert_eq!(o.map_or_else(fn_default_for_result, fn_closure), 12);
    assert_eq!(e.map_or_else(fn_default_for_result, fn_closure), 6);
}

ok_or() and ok_or_else()

如前所述,ok_or()ok_or_else()Option类型转换为Result类型。Some转成OkNone转成Err

  • ok_or() :默认的Err消息应作为参数传入。
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
fn main() {
    const ERR_DEFAULT: &str = "error message";let s = Some("abcde");
    let n: Option<&str> = None;let o: Result<&str, &str> = Ok("abcde");
    let e: Result<&str, &str> = Err(ERR_DEFAULT);
​
    assert_eq!(s.ok_or(ERR_DEFAULT), o); // Some(T) -> Ok(T)
    assert_eq!(n.ok_or(ERR_DEFAULT), e); // None -> Err(default)
}
  • ok_or_else() :类似于ok_or()。应将闭包作为参数传入。
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
fn main() {
    let s = Some("abcde");
    let n: Option<&str> = None;
    let fn_err_message = || "error message";let o: Result<&str, &str> = Ok("abcde");
    let e: Result<&str, &str> = Err("error message");
​
    assert_eq!(s.ok_or_else(fn_err_message), o); // Some(T) -> Ok(T)
    assert_eq!(n.ok_or_else(fn_err_message), e); // None -> Err(default)
}

as_ref() and as_mut()

如前所述,这些函数用于借用类型T作为引用或可变引用

  • as_ref() :从 Option<T>Option<&T> ,从Result<T, E>Result<&T, &E>
  • as_mut() :从 Option<T>Option<&mut T> ,从 Result<T, E>Result<&mut T, &mut E>
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
最全Excel 快捷键总结,告别鼠标!
本文为知乎答主宇轩原创,CDA数据分析师已获得授权 这里正在更新完毕最常用的快捷键和最完整的EXCEL快捷键,并且把最有用的都突出显示了。 快捷键的内容分三类: 1.F键:与F1-F12组合快捷键 2.Ctrl组合键 3.其他有用的快捷键 F键常用推荐 F1 :显示“Excel 帮助”任务窗格。(重要) Alt+Shift+F1/Shift+F11 :可插入新的工作表。 Shift+F2 :可添加或编辑单元格批注。(重要) Shift+F3 :显示“插入函数”对话框。 F4 :重复上一个命令或操作,在公
CDA数据分析师
2018/02/24
7.9K0
两个“神秘的”Excel快捷键
有时候,快捷键能够给我们带来很大的方便。大家最熟悉的快捷键可能是Ctrl+c和Ctrl+v了,很方便地为我们进行复制粘贴操作。
fanjy
2022/03/04
5680
两个“神秘的”Excel快捷键
电脑技巧:分享常用的电脑快捷键,赶快收藏吧!
今天给大家分享常用的电脑快捷键,赶快来收藏吧! 1、最常用快捷键 Ctrl + X:剪切。 Ctrl + V:粘贴。 Ctrl + Z:撤销。 Ctrl + A:选中全部内容。 DELETE:删除。 F2:重新命名所选项目。 F3:搜索文件或文件夹。 F5:刷新当前窗口。 Alt + F4:关闭当前项目或者退出当前程序。 Alt + Tab:在打开的项目之间切换。 Prt Scr Sysrq:截屏键 Shift + Delete:永久删除所选项,而不将它放到“回收站”中。 拖动某一项时按 CTRL:复制
小明互联网技术分享社区
2023/01/08
1.1K0
电脑技巧:分享常用的电脑快捷键,赶快收藏吧!
办公技巧:分享100个Excel快捷键,值得收藏!
85、Ctrl+Shift+Space在数据区域内,为选中当前区域;当前区域无数据时,选中整个工作表
小明互联网技术分享社区
2022/02/17
2.8K0
办公技巧:分享100个Excel快捷键,值得收藏!
Excel基础:一组快捷操作技巧
方法:选择要隐藏内容的单元格,按Ctrl+1组合键调出“设置单元格格式”对话框,选择该对话框中的“数字”选项卡,选取分类中的“自定义”,在“类型”框中输入:;;;,如下图1所示。
fanjy
2023/02/24
8510
Excel基础:一组快捷操作技巧
常用快捷键大全
F1 帮助 F2 改名 F3 搜索 F4 地址 F5 刷新 F6 切换 F8 安全模式 F10 菜单 F11 全屏 INS 插入模式 PRTSCSYSRQ 截屏 CAPSLOCK 大写字母锁定 DELETE 删除 ESC 退出 HOME 到开始或主程序 END 到结尾 PAGEUP 向上翻页 PAGEDOWN 向下翻页 TAB 改变焦点
张果
2022/05/09
4.8K0
常用快捷键大全
XMind 快捷键完整命令
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/134910.html原文链接:https://javaforall.cn
全栈程序员站长
2022/08/18
1.7K0
最常用Excel快捷键--提升工作效率
单元格左移:shift+tab 单元格右移:tab 单元格上移:shift+enter 单元格下移:enter SHIFT+左箭头键 :选定左边的字符 SHIFT+右箭头键 :选定右边的字符 Ctrl+1:打开单元格格式选项 Ctrl+2:黑体 B Ctrl+3:斜体 U Ctrl+4:下画线 Ctrl+9:隐藏一行单元格 Ctrl+0:隐藏一列单元格 Ctrl+Shift+9 取消隐藏行 Ctrl+Shift+0 取消隐藏列 持续显示单元格内的公式: “工具”——“公式审核”——“公式审核模式” 选中包
用户1756920
2018/06/20
1.1K0
最全的windows操作系统快捷键
一、常见用法:  F1           显示当前程序或者windows的帮助内容。  F2 运维
Java架构师必看
2021/03/22
2.2K0
Eclipse快捷键最有用的快捷键
Eclipse中10个最有用的快捷键组合  一个Eclipse骨灰级开发者总结了他认为最有用但又不太为人所知的快捷键组合。通过这些组合可以更加容易的浏览源代码,使得整体的开发效率和质量得到提升。     1. ctrl+shift+r:打开资源     这可能是所有快捷键组合中最省时间的了。这组快捷键可以让你打开你的工作区中任何一个文件,而你只需要按下文件名或mask名中的前几个字母,比如applic*.xml。美中不足的是这组快捷键并非在所有视图下都能用。 2. ctrl+o:快速outline    
Java学习123
2018/05/16
1.9K0
数据人必会的Excel|掌握32个Excel小技巧,成为效率达人(一)
作为数据分析师,有时候我们拿到的数据可能有成百上千行或者成百上千列,如果我们想要选中这成百上千数据中的一部分进行处理,常规的方法是拖动鼠标进行框选,但对于数据量大的情况这种方法不一定好,这时候就该Excel快捷键出马了。
数据万花筒
2021/01/12
1.8K0
Windows快捷键速查
1. 常用 快捷键 说明 Ctrl + X 剪切选定项。 Ctrl + C(或 Ctrl + Insert) 复制选定项。 Ctrl + V(或 Shift + Insert) 粘贴选定项。 Ctrl + Z 撤消操作。 Alt + Tab 在打开的应用之间切换。 Alt + F4 关闭活动项,或者退出活动应用。 Windows 徽标键 + L 锁定你的电脑。 Windows 徽标键 + D 显示和隐藏桌面。 F2 重命名所选项目。 F3 在文件资源管理器中搜索文件或文件夹。 F4 在文件资源管理器中显示地
hotarugali
2022/09/21
4.7K0
图表搬家
来这里找志同道合的小伙伴! 今天给大家聊一聊Excel图表的输出! 我们日常所做的图表,如果不是专门用做Excel报表的话,大部分还是要以图片的形式导出。 通常导出到PPT的情况比较多,主要用于课堂演示、商务汇报、年终总结、产品发布会等场合! 可能大家会觉得小魔方小题大做,不就是把图表从Excel转移到PPT中嘛,我也会呀。qq截图(CTRL+ALT+A)保存然后导入PPT就OK了;或者,更简单粗暴一点的,直接将图表复制黏贴(CTRL+C/CTRL+V)到PPT里也可以哦!!! 确实没错,这样的确可以满
数据小磨坊
2018/04/10
2.4K0
图表搬家
Excel小技巧29:编辑行或列的快捷键
如果了解Excel中的一些快捷键,特别是方便经常操作任务的快捷键,将会极大地提高我们使用Excel的效率。这里,介绍用于方便操作行和列的6个快捷键。
fanjy
2020/02/18
2.1K0
Excel 常用的九十九个技巧 Office 自学教程快速掌握办公技巧
Microsoft Excel 是微软为 Windows、macOS、Android 和 iOS 开发的电子表格软件,可以用来制作电子表格、完成许多复杂的数据运算,进行数据的分析和预测,并且具有强大的制作图表的功能。由于 Excel 具有十分友好的人机界面和强大的计算功能,它已成为国内外广大用户管理公司和个人财务、统计数据、绘制各种专业化表格的得力助手。允许用户自定义界面的电子制表软件包括字体、文字属性和单元格格式,它还引进了智能重算的功能,当单元格数据变动时,只有与之相关的数据才会更新,荒岛本次带来九十九个 Excel 技巧,提高您的办公效率。
ximagine
2023/05/05
7.8K0
【工具】一个投行工作十年MM的Excel操作大全
>移动到当前数据区域的边缘:CTRL+ 箭头键 移动到行首:HOME 移动到工作表的开头:CTRL+HOME 移动到工作表的最后一个单元格。:CTRL+END 向下移动一屏:PAGE DOWN 向上移动一屏:PAGE UP 向右移动一屏:ALT+PAGE DOWN 向左移动一屏:ALT+PAGE UP 移动到工作簿中下一个工作表:CTRL+PAGE DOWN 移动到工作簿中前一个工作表:CTRL+PAGE UP 移动到下一工作簿或窗口:CTRL+F6 或 CTRL+TAB 移动到前一工作簿或窗口:CTRL+
小莹莹
2018/04/19
4K0
windows10切换快捷键_Word快捷键大全
今天与大家分享一下最全的Windows10键盘快捷键汇总,包括:Windows10系统快捷键、Windows10内置应用快捷键、Windows10辅助功能快捷键、Microsoft Surface Hub快捷键、Win10手机Continuum模式快捷键,并且本文会随着Win10版本的更新和新快捷键的增加而持续更新。
全栈程序员站长
2022/11/10
6K0
20个Excel操作技巧,提高你的数据分析效率
今日头条丨一点资讯丨腾讯丨搜狐丨网易丨凤凰丨阿里UC大鱼丨新浪微博丨新浪看点丨百度百家丨博客中国丨趣头条丨腾讯云·云+社区
数据猿
2019/08/06
2.6K0
Windows系统快捷键汇总
shift + Alt + Print Screen(选中要截屏的地方,然后按这三个键,然后打开图画或者word,粘贴即可)
团团生活志
2022/08/16
1.1K0
VS2010版快捷键
这里我将会把一些无意中发现的VS2005中没有明确指出的快捷键共享出来,并不是所有的快捷键,或者常见的一些快捷键。 
DougWang
2020/02/18
1.2K0
相关推荐
最全Excel 快捷键总结,告别鼠标!
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档