引言

设计模式

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

在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. python3各数据类型的常用方法

    python3数据类型包括: 数字.字符串str.列表list.元组tuple.字典dict.集合set.布尔bool 1.字符串(str)-可变-用"".''定义 (1)uppe ...

  2. $\mathcal{2023WinterHoliday}$刷题总结

    \(\mathcal{2023WinterHoliday}\) \(\mathcal{CTF}\) \(\mathcal{web}\) 1.\(json格式:\)$json['x']=="w ...

  3. ACM-NEFUOJ-最小树-Prim算法

    最小树1 Description 某省长调查交通情况,发现本省交通事故发生不断,于是决定在本省内全部修建地铁. 该省长得到的统计表中列出了任意两市之间的距离,为了确保任何两个市都可以直接 或者间接实现 ...

  4. python入门教程之十八正则表达式

    re.match函数 re.match 尝试从字符串的起始位置匹配一个模式,如果不是起始位置匹配成功的话,match()就返回none. 函数语法: re.match(pattern, string, ...

  5. 【Note】贪心

    感谢 $ \text{orzws/chy} $ 倾情授课. 目录 -1. 证明方式 0. 朴素贪心 AT2557 [ARC073C] Ball Coloring P2587 [ZJOI2008]泡泡堂 ...

  6. LeeCode 动态规划(二)

    01背包问题 题目描述 有 n 件物品和容量为 w 的背包,给你两个数组 weights 和 values ,分别表示第 i 件物品的重量和价值,每件物品只能使用一次,求解将哪些物品装入背包可使得物品 ...

  7. openwrt开发使用-arping

    前言 IP冲突引起的网络异常,可以通过检查IP是否冲突,排除故障.我们可以用一些工具进行检查,例如arp-scan.arping软件进行查看. 这里使用arping进行检查设备的MAC地址,通过查查看 ...

  8. Java SpringBoot 7z 压缩、解压

    Java SpringBoot 7z 压缩.解压 cmd 7z 文件压缩 7z压缩测试 添加依赖 <dependency> <groupId>org.apache.common ...

  9. Go语言核心知识回顾(接口、Context、协程)

    温故而知新 接口 接口是一种共享边界,计算机系统的各个独立组件可以在这个共享边界上交换信息,在面向对象的编程语言,接口指的是相互独立的两个对象之间的交流方式,接口有如下好处: 隐藏细节: 对对象进行必 ...

  10. 如果你项目使用了MyBatis-Plus你一定要用它

    还是先举个例子,魂斗罗小游戏应该很多90后都玩过,那个时代没有Iphone,没有各种电子产品(小学初中时代),这种小游戏应该就是很多90后的青春,反正那个时候只要放假就白天黑夜得玩.它就是那种2个好基 ...