ascii - 为什么这些 ASCII 方法不一致?

标签 ascii rust

当我查看 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_upperis_lower 内联到is_alphabetic 中,那么您建议的更改会更好。 如果不是,那么 1 个函数调用可能现在是 3!那可能真的很糟糕。

这些类型的问题在这个级别上很难回答;人们必须对大型真实 Rust 代码进行一些查看(编辑 和分析!),以了解有关内联的优化器。

关于ascii - 为什么这些 ASCII 方法不一致?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27499367/

相关文章:

rust - 返回位置的值是否总是在父堆栈框架或接收框中分配?

rust - 引用 self : borrow error 方法的闭包

rust - 如何为 Cargo 中的子依赖项指定功能?

ascii - 这些 '{' 和 '}' 字符叫什么?

javascript - 为什么某些字符出现在 JS console.log 中的 'broken'?

c# - 读取可能包含非 ASCII 字符的流

rust - 如何返回具有实现 `Read` 和 `Write` 特征的泛型类型的结构?

java - 在Java中将十六进制字符串转换为ASCII

c++ - 如何在 Windows 10 中使用 C++ 输出低 ASCII?

rust - 为什么在名为!的宏中将 nom 的 CompleteStr 转换为字符串?返回结果?