Rust 为什么在使用正则表达式映射字符串时显然需要std::borrow::Cow?

Rust 为什么在使用正则表达式映射字符串时显然需要std::borrow::Cow?,rust,Rust,我正在解析器结构中实现一个代码解析器。我公开了一个pub方法lines,在删除注释的情况下迭代代码行。我想返回一个框 extern板条箱正则表达式;//1.0.5 使用regex::regex; 发布结构分析器{ 代码:String, } 静态注释:Regex=Regex::new(r”//*$”).unwrap(); impl解析器{ pub fn new(代码:String)->解析器{ 解析器{code} } 发布fn行(&self)->框{ 让线=自我 .代码 .split(“\n”)

我正在
解析器
结构中实现一个代码解析器。我公开了一个pub方法
lines
,在删除注释的情况下迭代代码行。我想返回一个

extern板条箱正则表达式;//1.0.5
使用regex::regex;
发布结构分析器{
代码:String,
}
静态注释:Regex=Regex::new(r”//*$”).unwrap();
impl解析器{
pub fn new(代码:String)->解析器{
解析器{code}
}
发布fn行(&self)->框{
让线=自我
.代码
.split(“\n”)
.map(|行|注释。替换|所有(行“”);
框::新(行)
}
}
但是,编译器给出了以下错误:

error[E0271]:类型不匹配解析`::Output==&str`
-->src/lib.rs:21:9
|
21 |框::新(行)
|^^^^^^^^^^^^^^^^^^^^^^^^^预期枚举'std::borrow::Cow',found&str
|
=注意:预期类型为'std::borrow::Cow[closure@src/图书馆:20:18:20:54]>`
=注意:强制转换到对象类型'dyn std::iter::Iterator'时需要`

它想让我使用
std::borrow::Cow
,但我在提到这个要求时找不到任何东西。为什么这是必要的?我可以避免吗?

强烈建议您阅读您正在使用的所有类型和方法的文档。例如,记录为:

pub fn replace_all<'t, R: Replacer>(
    &self, 
    text: &'t str, 
    rep: R
) -> Cow<'t, str>
//   ^^^^^^^^^^^^
另见:


强烈建议阅读您正在使用的所有类型和方法的文档。例如,记录为:

pub fn replace_all<'t, R: Replacer>(
    &self, 
    text: &'t str, 
    rep: R
) -> Cow<'t, str>
//   ^^^^^^^^^^^^
另见:


正如您已经发现的,来自

在您的情况下,有一种非常危险且令人沮丧的方法来获取
&str的迭代器:

extern crate regex; // 1.0.5

use regex::Regex;
use std::borrow::Cow;

pub struct Parser {
    code: String,
}

impl Parser {
    pub fn new(code: String) -> Parser {
        Parser { code }
    }

    pub fn lines<'a>(&'a self, comment: Regex) -> Box<Iterator<Item = &'a str> + 'a> {
        let lines = self
            .code
            .split("\n")
            .map(move |line| comment.replace_all(line, ""))
            .map(|cow| match cow {
                Cow::Borrowed(sref) => sref,
                Cow::Owned(_) => panic!("I hope never to be here"),
            });
        Box::new(lines)
    }
}

fn main() {
    let comment: Regex = Regex::new(r"//.*$").unwrap();

    let p = Parser::new("hello\nworld".to_string());

    for item in p.lines(comment) {
        println!("{:?}", item);
    }
}

正如你已经发现的,来自

在您的情况下,有一种非常危险且令人沮丧的方法来获取
&str的迭代器:

extern crate regex; // 1.0.5

use regex::Regex;
use std::borrow::Cow;

pub struct Parser {
    code: String,
}

impl Parser {
    pub fn new(code: String) -> Parser {
        Parser { code }
    }

    pub fn lines<'a>(&'a self, comment: Regex) -> Box<Iterator<Item = &'a str> + 'a> {
        let lines = self
            .code
            .split("\n")
            .map(move |line| comment.replace_all(line, ""))
            .map(|cow| match cow {
                Cow::Borrowed(sref) => sref,
                Cow::Owned(_) => panic!("I hope never to be here"),
            });
        Box::new(lines)
    }
}

fn main() {
    let comment: Regex = Regex::new(r"//.*$").unwrap();

    let p = Parser::new("hello\nworld".to_string());

    for item in p.lines(comment) {
        println!("{:?}", item);
    }
}

这是对我来说最好的解决办法

replace_all
不是这个用例的好方法。我只想删除评论。我从不需要在字符串中插入任何内容。如果是这样的话,我应该能够处理字符串切片。无需使用
replace\u all
引入的
Cow
类型。以下是我是如何做到的

impl Parser {
    pub fn lines<'a>(&'a self) -> Box<dyn Iterator<Item = &'a str> + 'a> {
        let lines = self.code
            .lines()
            .map(|line| { line.split("//").next().unwrap() })
            .map(|line| line.trim())
            .filter(|line| line.len() > 0);

        Box::new(lines)
    }
}
impl解析器{
酒吧fn线盒{
让line=self.code
.行()
.map(| line |{line.split(“/”).next().unwrap()})
.map(| line | line.trim())
.filter(| line | line.len()>0);
框::新(行)
}
}

这是针对我的案例的最佳解决方案

replace_all
不是这个用例的好方法。我只想删除评论。我从不需要在字符串中插入任何内容。如果是这样的话,我应该能够处理字符串切片。无需使用
replace\u all
引入的
Cow
类型。以下是我是如何做到的

impl Parser {
    pub fn lines<'a>(&'a self) -> Box<dyn Iterator<Item = &'a str> + 'a> {
        let lines = self.code
            .lines()
            .map(|line| { line.split("//").next().unwrap() })
            .map(|line| line.trim())
            .filter(|line| line.len() > 0);

        Box::new(lines)
    }
}
impl解析器{
酒吧fn线盒{
让line=self.code
.行()
.map(| line |{line.split(“/”).next().unwrap()})
.map(| line | line.trim())
.filter(| line | line.len()>0);
框::新(行)
}
}

Idiomatic Rust使用
snake\u case
表示变量、方法、宏和字段<对于类型,代码>大写
;对于静力学和常数,
SNAKE\u案例
。请改为使用
静态注释
。惯用的Rust使用
snake\u case
表示变量、方法、宏和字段<对于类型,代码>大写
;对于静力学和常数,
SNAKE\u案例
。请改为使用
静态注释
。坦率地说,这是一个糟糕的建议。如果永远不需要运行
replace\u all
调用(因此永远不需要返回
Cow::Owned
),那么它就不应该在那里。想必OP确实需要出于某种原因删除注释,因此这总是会引起恐慌。我也不同意返回
String
s通常是“更好”的说法;现在您必须为每一行重新分配,这似乎是对性能的极大浪费。事实上,我只需要删除注释。不需要复印件。我认为
replace\u all
对我来说是一个糟糕的方法选择。我发布了一个更好的方法的答案。坦率地说,这是一个糟糕的建议。如果永远不需要运行
replace\u all
调用(因此永远不需要返回
Cow::Owned
),那么它就不应该在那里。想必OP确实需要出于某种原因删除注释,因此这总是会引起恐慌。我也不同意返回
String
s通常是“更好”的说法;现在您必须为每一行重新分配,这似乎是对性能的极大浪费。事实上,我只需要删除注释。不需要复印件。我认为
replace\u all
对我来说是一个糟糕的方法选择。我发布了一个更好的方法的答案。谢谢你关于文档的建议。我来自JS,它的对象很少有很好的文档记录。所以我习惯于在REPL中进行内省,以找出对象具有哪些字段。我把这个习惯带到了铁锈里。但现在,从现在起,我一直在用手头的文档开发我的锈迹,这是一个更好的体验!谢谢感谢您对文档的推荐。我来自JS,它的对象很少有很好的文档记录。所以我习惯于在REPL中进行内省,以找出对象具有哪些字段。我把这个习惯带到了铁锈里。但现在,从现在起,我一直在用手头的文档开发我的锈迹,这是一个更好的体验!谢谢