命名规范 您所在的位置:网站首页 dos文件取名规则是什么意思啊 命名规范

命名规范

2024-06-19 23:10| 来源: 网络整理| 查看: 265

命名规范

基本的 Rust 命名规范在 RFC 430 中有描述。

通常,对于 type-level 的构造 Rust 倾向于使用驼峰命名法,而对于 value-level 的构造使用蛇形命名法。详情如下:

条目惯例 包 Cratesunclear 模块 Modulessnake_case 类型 TypesUpperCamelCase 特征 TraitsUpperCamelCase 枚举 EnumerationsUpperCamelCase 结构体 StructsUpperCamelCase 函数 Functionssnake_case 方法 Methodssnake_case 通用构造器 General constructorsnew or with_more_details 转换构造器 Conversion constructorsfrom_some_other_type 宏 Macrossnake_case! 局部变量 Local variablessnake_case 静态类型 StaticsSCREAMING_SNAKE_CASE 常量 ConstantsSCREAMING_SNAKE_CASE 类型参数 Type parametersUpperCamelCase,通常使用一个大写字母: T 生命周期 Lifetimes通常使用小写字母: 'a,'de,'src Featuresunclear but see C-FEATURE

对于驼峰命名法,复合词的缩略形式我们认为是一个单独的词语,所以只对首字母进行大写:使用 Uuid 而不是 UUID,Usize 而不是 USize,Stdin 而不是 StdIn。

对于蛇形命名法,缩略词用全小写:is_xid_start。

对于蛇形命名法(包括全大写的 SCREAMING_SNAKE_CASE),除了最后一部分,其它部分的词语都不能由单个字母组成: btree_map 而不是 b_tree_map,PI_2 而不是 PI2.

包名不应该使用 -rs 或者 -rust 作为后缀,因为每一个包都是 Rust 写的,因此这种多余的注释其实没有任何意义。

特征命名

特征的名称应该使用动词,而不是形容词或者名词,例如 Print 和 Draw 明显好于 Printable 和 Drawable。

类型转换要遵守 as_,to_,into_ 命名惯例(C-CONV)

类型转换应该通过方法调用的方式实现,其中的前缀规则如下:

方法前缀性能开销所有权改变 as_Freeborrowed -> borrowed to_Expensiveborrowed -> borrowedborrowed -> owned (non-Copy types)owned -> owned (Copy types) into_Variableowned -> owned (non-Copy types)

例如:

str::as_bytes() 把 str 变成 UTF-8 字节数组,性能开销是 0。输入是一个借用的 &str,输出也是一个借用的 &str Path::to_str 会执行一次昂贵的 UTF-8 字节数组检查,输入和输出都是借用的。对于这种情况,如果把方法命名为 as_str 是不正确的,因为这个方法的开销还挺大 str::to_lowercase() 在调用过程中会遍历字符串的字符,且可能会分配新的内存对象。输入是一个借用的 str,输出是一个有独立所有权的 String String::into_bytes() 返回 String 底层的 Vec 数组,转换本身是零消耗的。该方法获取 String 的所有权,然后返回一个新的有独立所有权的 Vec

当一个单独的值被某个类型所包装时,访问该类型的内部值应通过 into_inner() 方法来访问。例如将一个缓冲区值包装为 BufReader 类型,还有 GzDecoder、AtomicBool 等,都是这种类型。

如果 mut 限定符在返回类型中出现,那么在命名上也应该体现出来。例如,Vec::as_mut_slice 就说明它返回了一个 mut 切片,在这种情况下 as_mut_slice 比 as_slice_mut 更适合。

#![allow(unused)] fn main() { // 返回类型是一个 `mut` 切片 fn as_mut_slice(&mut self) -> &mut [T]; } 标准库中的一些例子 Result::as_ref RefCell::as_ptr slice::to_vec Option::into_iter 读访问器(Getter)的名称遵循 Rust 的命名规范(C-GETTER)

除了少数例外,在 Rust代码中 get 前缀不用于 Getter。

#![allow(unused)] fn main() { pub struct S { first: First, second: Second, } impl S { // 而不是 get_first pub fn first(&self) -> &First { &self.first } // 而不是 get_first_mut,get_mut_first,or mut_first pub fn first_mut(&mut self) -> &mut First { &mut self.first } } }

至于上文提到的少数例外,如下:当有且仅有一个值能被 Getter 所获取时,才使用 get 前缀。例如,Cell::get 能直接访问到 Cell 中的内容。

有些 Getter 会在过程中执行运行时检查,那么我们就可以考虑添加 _unchecked Getter 函数,这个函数虽然不安全,但是往往具有更高的性能。 典型的例子如下:

#![allow(unused)] fn main() { fn get(&self, index: K) -> Option; fn get_mut(&mut self, index: K) -> Option; unsafe fn get_unchecked(&self, index: K) -> &V; unsafe fn get_unchecked_mut(&mut self, index: K) -> &mut V; } 标准库示例 std::io::Cursor::get_mut std::ptr::Unique::get_mut std::sync::PoisonError::get_mut std::sync::atomic::AtomicBool::get_mut std::collections::hash_map::OccupiedEntry::get_mut ::get_unchecked 一个集合上的方法,如果返回迭代器,需遵循命名规则:iter,iter_mut,into_iter (C-ITER) #![allow(unused)] fn main() { fn iter(&self) -> Iter // Iter implements Iterator fn iter_mut(&mut self) -> IterMut // IterMut implements Iterator fn into_iter(self) -> IntoIter // IntoIter implements Iterator }

上面的规则适用于同构性的数据集合。与之相反,str 类型是一个 UTF-8 字节数组切片,与同构性集合有一点微妙的差别,它可以认为是字节集合,也可以认为是字符集合,因此它提供了 str::bytes 去遍历字节,还有 str::chars 去遍历字符,而并没有直接定义 iter 等方法。

上述规则只适用于方法,并不适用于函数。例如 url 包的 percent_encode 函数返回一个迭代器用于遍历百分比编码(Percent encoding)的字符串片段. 在这种情况下,使用 iter/iter_mut/into_iter 诸如此类的函数命名无法表达任何具体的含义。

标准库示例 Vec::iter Vec::iter_mut Vec::into_iter BTreeMap::iter BTreeMap::iter_mut 迭代器的类型应该与产生它的方法名相匹配(C-ITER-TY)

例如形如 into_iter() 的方法应该返回一个 IntoIter 类型,与之相似,其它任何返回迭代器的方法也应该遵循这种命名惯例。

上述规则主要应用于方法,但是经常对于函数也适用。例如上文提到的 url 包中的 percent_encode 函数,返回了一个 PercentEncode 类型。

特别是,当这些类型跟包名前缀一起使用时,将具备非常清晰的含义,例如 vec::IntoIter。

标准库示例 Vec::iter returns Iter Vec::iter_mut returns IterMut Vec::into_iter returns IntoIter BTreeMap::keys returns Keys BTreeMap::values returns Values

Cargo Feature 的名称不应该包含占位词(C-FEATURE)

不要在 Cargo feature 中包含无法传达任何意义的词,例如 use-abc 或 with-abc,直接命名为 abc 即可。

一个典型的例子就是:一个包对标准库有可选性的依赖。标准的写法如下:

# 在 Cargo.toml 中 [features] default = ["std"] std = [] #![allow(unused)] fn main() { // 在我们自定义的 lib.rs 中 #![cfg_attr(not(feature = "std"), no_std)] }

除了 std 之外,不要使用任何 ust-std 或者 with-std 等自以为很有创造性的名称。

命名要使用一致性的词序(C-WORD-ORDER)

这是一些标准库中的错误类型:

JoinPathsError ParseBoolError ParseCharError ParseFloatError ParseIntError RecvTimeoutError StripPrefixError

它们都使用了 谓语-宾语-错误 的词序,如果我们想要表达一个网络地址无法分析的错误,由于词序一致性的原则,命名应该如下 ParseAddrError,而不是 AddrParseError。

词序和个人习惯有很大关系,想要注意的是,你可以选择合适的词序,但是要在包的范畴内保持一致性,就如标准库中的包一样。



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有