macro_rules!宏采用字符串文字“ ...”,扩展为“ ...”和b“ ...”

zwo*_*wol 5 macros rust

我想写一个macro_rules!宏,它的参数是一个,ident并且是字符串文字列表。宏的扩展需要同时包含字符串文字和相应的字节文字。该宏用于测试,将仅与仅包含U + 0000 ... U + 007F范围内的字符的字符串一起使用。如果将字符串文字以外的任何内容提供给宏会导致编译时错误,则可以。

如果当前无法不使用过程宏来实现,请告诉我,不要费心实际编写过程宏;-)

所需的调用和扩展是这样的:

all_s! isalpha [ "abcdefghijklmnopqrstuvwxyz" /* , ... */ ];
Run Code Online (Sandbox Code Playgroud)

=>

assert!(isalpha("abcdefghijklmnopqrstuvwxyz"));
assert!("abcdefghijklmnopqrstuvwxyz".chars().all(|b| isalpha(b));
assert!(isalpha(b"abcdefghijklmnopqrstuvwxyz"));
assert!(b"abcdefghijklmnopqrstuvwxyz".iter().all(|b| isalpha(b)));
/* ... */
Run Code Online (Sandbox Code Playgroud)

据我所知:

macro_rules! all_s {
    ($what: ident, $( $str: tt ),* ) => {{
        $(
            assert!($what($str));
            assert!($str.chars().all(|b| $what(b));
            assert!($what(BYTE_LITERAL!($str)));
            assert!(BYTE_LITERAL!($str).iter().all(|b| $what(b)));
        )*
    }}
}
Run Code Online (Sandbox Code Playgroud)

但是我不知道该说什么BYTE_LITERAL!,而且我也收到错误消息,提示我没有正确编写匹配模式,例如“ macro all_s!期望没有ident参数,给定'isalpha'” “ $ what:ident”就在那里。

Pet*_*all 2

我也不知道如何拒绝tt不是字符串文字的。

如果您利用参数是字符串这一事实,那么类型检查器将负责产生错误。

macro_rules! all_s {
    ($what: ident, $( $str: tt ),* ) => {{
        $(
            assert!($what($str));
            assert!(str::chars($str).all(|c| char::is_alphabetic(c)));
            assert!(str::chars($str).all(|c| char::is_alphabetic(c)));
        )*
    }}
}
Run Code Online (Sandbox Code Playgroud)

在您的问题代码中,您尝试将相同的isalpha值与char和的值一起使用u8。您必须首先将chars 转换为s:u8

assert!(str::chars($str)
            .map(|c| c as u8) // this is safe given the assumption you stated
            .all(|b| b < 0x7F));
Run Code Online (Sandbox Code Playgroud)

  • @zwol 以你的高声誉,我想你会知道[不要在一篇文章中提出多个问题](http://meta.stackexchange.com/questions/39223/one-post-with-multiple-questions-或多个帖子)。这样做可以得到这样的有效答案。 (2认同)