【问题标题】:Rust String vs &str iteratorsRust 字符串与 &str 迭代器
【发布时间】:2020-11-18 21:04:17
【问题描述】:

我正在尝试编写一个接受令牌列表的函数。但是我在使它足够通用以处理两个非常相似的调用时遇到了问题:

let s = String::from("-abc -d --echo");

parse( s.split_ascii_whitespace() );
parse( std::env::args() );

我有没有办法为parse 编写一个函数签名来接受这两种方法?

我现在的解决方案需要复制函数体:

fn main() {
    let s = String::from("-abc -d --echo");

    parse_args( s.split_ascii_whitespace() );
    parse_env( std::env::args() );
}

fn parse_env<I: Iterator<Item=String>>(mut it: I) {
    loop {
        match it.next() {
            None => return,
            Some(s) => println!("{}",s),
        }
    }
}

fn parse_args<'a, I: Iterator<Item=&'a str>>(mut it: I) {
    loop {
        match it.next() {
            None => return,
            Some(s) => println!("{}",s),
        }
    }
}

如果不可能,那么一些关于如何使用特征以便函数可以使用相同名称的建议会很好。

【问题讨论】:

    标签: rust iterator traits


    【解决方案1】:

    您可以要求项目类型为AsRef&lt;str&gt;,这将包括&amp;strString

    fn parse<I>(mut it: I)
    where
        I: Iterator,
        I::Item: AsRef<str>,
    {
        loop {
            match it.next() {
                None => return,
                Some(s) => println!("{}", s.as_ref()),
            }
        }
    }
    

    【讨论】:

    • 如果你喜欢 impl trait in argument position(这是个人喜好问题),你也可以将签名写成fn parse(mut it: impl Iterator&lt;Item = impl AsRef&lt;str&gt;&gt;)
    【解决方案2】:

    根据您的用例,您可以尝试:

    fn main() {
        let s = String::from("-abc -d --echo");
    
        parse( s.split_ascii_whitespace() );
        parse( std::env::args() );
    }
    
    fn parse<T: std::borrow::Borrow<str>, I: Iterator<Item=T>>(mut it: I) {
        loop {
            match it.next() {
                None => return,
                Some(s) => println!("{}",s.borrow()),
            }
        }
    }
    

    我使用Borrow 作为获得&amp;str 的一种方式,但您的具体用例可能由其他可能自定义的特征提供服务。

    【讨论】:

    • BorrowAsRef 令人困惑地相似。从历史上看,引入Borrow 的原因是哈希映射需要HashEqOrd 的借用值和原始值实现之间的一致性。由于AsRef 没有这些附加要求,因此需要一个新特征。在这个用例中,额外的要求是无关紧要的——我们只想将我们得到的任何项目类型转换为&amp;str,所以我相信AsRef在这里更合适,但我承认差异是相当哲学的在这种特殊情况下。
    • @SvenMarnach 补充一下您所写的内容,AsRef&lt;T&gt; 是一个众所周知的成语,在 stdlib 和其他地方有很多用途。例如,AsRef&lt;Path&gt; 用于以多种方式创建 accept paths(从字符串、OsStrPathBuf 等),AsRef&lt;OsStr&gt; 用于需要操作系统字符串的事物,例如 @987654322 @, 等等。 AsRef&lt;str&gt; 对任何遇到这些的人来说都很熟悉,而 Borrow&lt;str&gt; 会错误地指出额外的要求。
    猜你喜欢
    • 2012-10-23
    • 1970-01-01
    • 2011-07-22
    • 2012-02-24
    • 2012-08-19
    • 1970-01-01
    • 1970-01-01
    • 2014-04-21
    • 1970-01-01
    相关资源
    最近更新 更多