引言

设计模式

在开发程序中,我们必须解决许多问题。一个程序可以看作是一个问题的解决方案。它也可以被看作是许多不同问题的解决方案的集合。所有这些解决方案共同解决一个更大的问题。

在Rust中的设计模式

有许多问题的形式是相同的,由于事实上,rust不是面向对象设计,模式不同于其他面向对象程序设计语言,虽然细节是不同的,因为他们有相同的形式,他们可以解决使用相同的基本方法。

设计模式是解决编写软件时常见问题的方法。

反模式是解决这些相同问题的方法。

然而,尽管设计模式给我们带来了好处,反模式却带来了更多的问题。

惯用法,是编码是要遵守的指南,他们是社区的社区规范,你可以破他们,但如果你这样做,你应该有一个很好的理由。

TODO: 说明为什么Rust是一个有点特殊功能要素,类型系统,借用检查。

Idioms

惯用法是一种常用的风格和模式,在很大程度上得到了社区的认可,他们是指导方针,编写惯用代码可以让其他开发人员理解正在发生的事情,因为他们熟悉代码的形式。

计算机理解编译器生成的机器代码,因此,这种语言对开发人员来说是最有利的,所以既然我们有了这个抽象层,为什么不好好利用它,然它变得简单呢?

记住KISS原则,"保持简单,Stupid。" 他声称“大多数系统如果有保持简单而不是复杂,就能工作的最好,因此,简单应该是设计的一个关键目标,应该避免不必要的复杂性。

代码是给人类而不是计算机去理解的。

Use borrowed types for arguments

对参数使用borrowed types

描述

当你决定使用哪种参数作为函数参数时,使用强制解引用(deref coerrcion) 的目标可以增加代码的灵活性。这样,函数将接受更多的输入类型。

这不经限于可切片类型或者胖指针类型。事实上,你总是更喜欢borrowed type 而不是 borrowing the owned type, 例如, &str Over &String, &[T] Over &Vec<T>, or &T Over &Box<T>

对于owned type 已经提供了间接层的实例,使用borrowed type可以避免使用间接层。例如,String有一个间接层,因此&String将有两个间接层。我们可以通过使用&str来避免这种情况,并且在调用函数时让&String强制转换到&str.

例子

在本例中,我们将说明使用&String作为函数参数与使用&str的区别。但是这些思想也适用于使用&Vec <T> 与使用&[T] 或者使用&T 与&Box<T> .

考虑一个例子,我们希望确定一个单词是否包含三个连续的元音,我们不需要拥有字符串来确定这一点。因为我们将采用一个引用。

代码可能是这样的

fn three_vowels(word: &String) -> bool {
let mut vowel_ocunt = 0;
for c in word.chars() {
match c {
'a' | 'e' | 'i' | 'o' | 'u' => {
vowel_count += 1;
if vowel_count >= 3 {
return true;
}
}
_ => vowel_count = 0;
}
}
false
}
fn main() {
let ferris = "Ferris".to_string();
let curious = "Curious".to_string();
println!("{}: {}", ferris, three_vowels(&ferris));
println!("{}: {}", curious, three_vowels(&curious)); // This work fine,but the following two lines would fail;
// println!("Ferris: {}", three_vowles("Ferris"));
// println!("Currious: {}", three_vowles("Curious"));
}

这样做很好,因为我们将&String类型作为参数传递。我们在最后两行中进行注释,这个示例就会失败,因为&str类型不会强制转换为&String。我们可以通过简单地修改参数的类型来解决这个问题。

例如,我们将函数声明更改为

fn three_vowels(word: &str) -> bool {

然后两个版本将编译并打印相同的输出

Ferris: false
Curious: true

但是,等等,这还不是全部。这个故事还有更多内容。很可能你会对自己说:这不重要,我们永远不会使用&' static str作为输入方式(就像我们使用"Ferris"时所作的那样)。即使忽略这个特殊的示例,您可能仍然会发现使用&str比使用&String更具灵活性.

现在让我们举一个例子,有人给我们一个句子,我们想确定句子中的任何一个单词是否有一个包含三个连续元音的单词,我们可能应该利用我们已经定义的函数,简单的输入句子中的每个单词。

下面试一个例子:

fn three_vowels(word: &String) -> bool {
let mut vowel_ocunt = 0;
for c in word.chars() {
match c {
'a' | 'e' | 'i' | 'o' | 'u' => {
vowel_count += 1;
if vowel_count >= 3 {
return true;
}
}
_ => vowel_count = 0;
}
}
false
}
fn main() {
let sentence_string = "Once upon a time, there was a friendly curious crab named Ferris".to_string();
for word in sentence_string.split(' ') {
if three_vowels(word) {
println!("{} has three consecutive vowels!", word);
}
}
}

带有&str类型参数声明的函数运行这个例子将产生

curious has three consecutive vowels!

但是,我们的函数使用&String类型的参数声明时,这个示例将不会运行。这是因为字符串切片是&str而不是&String,需要分配内存将&str转换为&String,但是这不是隐式的,而从String转换为&str是廉价且隐式的。

参见

原文: Rust Design Patterns

(翻译)Rust中的设计模式(1-Use borrowed types for arguments)的更多相关文章

  1. 【翻译】R 中的设计模式

    目录 R 中的设计模式 不动点算法 包装器模式 接口模式 柯里化(Currying) 闭包(Closures) 缓存模式 计数器模式 R 中的设计模式 本文翻译自 Design Patterns in ...

  2. Rust中的RefCell和内部可变性

    RefCell Rust在编译阶段会进行严格的借用规则检查,规则如下: 在任意给定时间,要么只能有一个可变引用,要么只能有多个不可变引用. 引用必须总是有效. 即在编译阶段,当有一个不可变值时,不能可 ...

  3. 【译】理解Rust中的闭包

    原文标题:Understanding Closures in Rust 原文链接:https://medium.com/swlh/understanding-closures-in-rust-21f2 ...

  4. 【译】深入理解Rust中的生命周期

    原文标题:Understanding Rust Lifetimes 原文链接:https://medium.com/nearprotocol/understanding-rust-lifetimes- ...

  5. 【原创翻译】认识MVC设计模式:web应用开发的基础(实际编码篇)

    原文地址:http://www.larryullman.com/2009/10/15/understanding-mvc-part-3/ 全系列INDEX [原创翻译]认识MVC设计模式:web应用开 ...

  6. 刷完欧拉计划中难度系数为5%的所有63道题,我学会了Rust中的哪些知识点?

    我为什么学Rust? 2019年6月18日,Facebook发布了数字货币Libra的技术白皮书,我也第一时间体验了一下它的智能合约编程语言MOVE,发现这个MOVE是用Rust编写的,看来想准确理解 ...

  7. 【译】Rust中的array、vector和slice

    原文链接:https://hashrust.com/blog/arrays-vectors-and-slices-in-rust/ 原文标题:Arrays, vectors and slices in ...

  8. 【译】理解Rust中的局部移动

    原文标题:Understanding Partial Moves in Rust 原文链接:https://whileydave.com/2020/11/30/understanding-partia ...

  9. 【译】理解Rust中的Futures (一)

    原文标题:Understanding Futures In Rust -- Part 1 原文链接:https://www.viget.com/articles/understanding-futur ...

  10. 【译】理解Rust中的Futures(二)

    原文标题:Understanding Futures in Rust -- Part 2 原文链接:https://www.viget.com/articles/understanding-futur ...

随机推荐

  1. 最新版 Harbor 在ubuntu系统上安装

    最新版 Harbor 在ubuntu系统上安装 The latest version of Harbor is installed on the ubuntu system 安装docker Inst ...

  2. python入门教程之十三错误和异常

    作为 Python 初学者,在刚学习 Python 编程时,经常会看到一些报错信息,在前面我们没有提及,这章节我们会专门介绍. Python 有两种错误很容易辨认:语法错误和异常. Python as ...

  3. abc294G

    Upd G 看上好模板的样子, 果然是个模板题 好题 , 首先考虑这张图的 \(Euler \ Tour\), 简单点说, 就是dfs一遍, 把每个点入栈出栈顺序存起来, 举个例子· 2 1 2 2 ...

  4. 多表查询和python操作mysql

    目录 多表查询的两种方法 方法1:连表操作 方法2:子查询 小知识点补充说明 可视化软件NaviCat 多表查询练习题 1.查询所有的课程的名称以及对应的任课老师姓名 2.查询平均成绩大于八十分的同学 ...

  5. 在英特尔 CPU 上加速 Stable Diffusion 推理

    前一段时间,我们向大家介绍了最新一代的 英特尔至强 CPU (代号 Sapphire Rapids),包括其用于加速深度学习的新硬件特性,以及如何使用它们来加速自然语言 transformer 模型的 ...

  6. sql 开窗函数排序遇到空值的处理办法

    sql sever默认null最小 升序排序 null值在最前面,若要放在后面,则: order by case when col is null then 1 else 0 end, col 降序排 ...

  7. 安装MinGW,使用vscode进行C++编译

    1.下载 https://osdn.net/projects/mingw/downloads/68260/mingw-get-setup.exe/ 2.安装 直接默认所有选项安装即可,可以更换安装位置 ...

  8. C# 如何设计一个好用的日志库?【架构篇】

    〇.前言 相信你在实际工作期间经常遇到或听到这样的说法:   "我现在加一下日志,等会儿你再操作下."   "只有在程序出问题以后才会知道打一个好的日志有多么重要.&qu ...

  9. 记一道国际赛CTF web题

    这是一篇关于打d3ctf坐牢,无奈去打国际赛的题解. TAMUCTF [Blackbox] 首先打开页面,然后发现一个登陆框 刚开始最先想到就是弱口令登陆,尝试几个后发现登陆不进去. 之后我就换了一个 ...

  10. Docker compose单机编排工具

    Docker compose单机编排工具 目录 Docker compose单机编排工具 docker-compose介绍 Docker Compose使用的三步: docker-compose安装部 ...