当我查看rust ASCII operations时,感觉
之间存在一致性问题is_lowercase / is_uppercase:
pub fn is_uppercase(&self) -> bool {
(self.chr - b'A') < 26
}
is_alphabetic:
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()
}
答案 0 :(得分:0)
他们是等同的。 is_alphabetic
可以使用字节文字而不是十六进制代码编写,使其更具可读性并与其他函数匹配:
pub fn is_alphabetic(&self) -> bool {
(self.chr >= b'A' && self.chr <= b'Z') ||
(self.chr >= b'a' && self.chr <= b'z')
}
答案 1 :(得分:0)
is_alphabetic
中的值肯定对应于字母的相应ASCII值。您可以使用以下方式验证:
println!("0x{:x} 0x{:x}", b'A', b'A');
println!("0x{:x} 0x{:x}", b'a', b'z');
is_alphabetic
依赖于ASCII小写和大写字母是连续的(不幸的是,彼此之间没有)。它可以写成:
pub fn is_alphabetic(&self) -> bool {
(self.chr >= b'A' && self.chr <= b'Z') || (self.chr >= b'a' && self.chr <= b'z')
}
// Or
pub fn is_alphabetic(&self) -> bool {
self.is_upper() || self.is_lower()
}
is_lower
和is_upper
都依赖无符号数学下溢才是正确的。如果a
为0x61
且z
为0x7A
,并且我们从两者中减去a
,则会得到0
和25
。但是,如果它比a
少一个,我们会得到0xFF
。 0xFF
不是< 26
,因此检查失败。
答案 2 :(得分:0)
由于问题改为关于性能,我将添加第二个答案。
首先,我创建了一个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());
}
在游戏围栏中,确保优化设置为-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代码中查看(编辑和分析!)才能理解优化器的内联。