当我查看 rust ASCII operations感觉之间存在一致性问题
is_lowercase/is_uppercase:
pub fn is_uppercase(&self) -> bool {
(self.chr - b'A') < 26
}
是字母表:
pub fn is_alphabetic(&self) -> bool {
(self.chr >= 0x41 && self.chr <= 0x5A) || (self.chr >= 0x61 && self.chr <= 0x7A)
}
有充分的理由吗?这两种方法是完全等效的还是我遗漏了什么? 所有这些功能都标记为稳定,所以我很困惑。
编辑:
为了说得更清楚,我期望的是决定下层/上层的最佳(在性能/可读性/通用实践方面)实现
pub fn is_alphabetic(&self) -> bool {
self.is_lowercase() || self.is_uppercase()
}
最佳答案
由于问题变成了关于性能的问题,我将添加第二个答案。
首先,我创建了一个 Ascii 模块的克隆 (playpen):
pub struct Alpha(u8);
impl Alpha {
#[inline(never)]
pub fn is_uppercase_sub(&self) -> bool {
(self.0 - b'A') < 26
}
#[inline(never)]
pub fn is_uppercase_range(&self) -> bool {
self.0 >= 0x41 && self.0 <= 0x5A
}
}
fn main() {
let yes = Alpha(b'A');
let no = Alpha(b'a');
println!("{}, {}", yes.is_uppercase_sub(), yes.is_uppercase_range());
}
在 playpen 中,确保优化设置为 -O2
,然后单击 IR
。这显示了 LLVM I中间 R 表示。如果您愿意,它就像一个更高级别的程序集。
有很多输出,但要查找带有 fastcc
的部分。我删除了各种位以使此代码更清晰,但您可以看到调用了完全相同函数,即使我们的代码调用了两种不同的实现,一种是减法,另一种是范围:
%3 = call fastcc zeroext i1 @_ZN5Alpha16is_uppercase_sub20h63aa0b11479803f4laaE
%5 = call fastcc zeroext i1 @_ZN5Alpha16is_uppercase_sub20h63aa0b11479803f4laaE
LLVM 优化器可以判断这些实现是相同的,所以这实际上取决于开发人员的偏好。如果您愿意,您也许可以提交到 Rust 中以使它们保持一致! ^_^
询问 is_alphabetic
更难;内联将在这里发挥作用。 如果 LLVM 将is_upper
和is_lower
内联到is_alphabetic
中,那么您建议的更改会更好。 如果不是,那么 1 个函数调用可能现在是 3!那可能真的很糟糕。
这些类型的问题在这个级别上很难回答;人们必须对大型真实 Rust 代码进行一些查看(编辑 和分析!),以了解有关内联的优化器。
关于ascii - 为什么这些 ASCII 方法不一致?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27499367/