我正在尝试编写一个带有正则表达式和字符串/ str的Rust函数,并返回该正则表达式中所有已命名捕获的HashMap.这是代码:
use std::collections::HashMap;
use regex::Regex;
fn get_matches<'a>(line: &'a str, re: &Regex) -> HashMap<&'a str, &'a str> {
let mut results = HashMap::new();
match re.captures(line) {
None => { return results; },
Some(caps) => {
for (name, value) in caps.iter_named() {
if let Some(value) = value {
results.insert(name, value);
}
}
}
}
results
}
我得到这个编译器错误(Rust 1.9.0):
error: `caps` does not live long enough
for (name, value) in caps.iter_named() {
^~~~
note: reference must be valid for the lifetime 'a as defined on the block at 6:79...
fn get_matches<'a>(line: &'a str, re: &Regex) -> HashMap<&'a str, &'a str> {
let mut results = HashMap::new();
match re.captures(line) {
None => { return results; },
Some(caps) => {
...
note: ...but borrowed value is only valid for the match at 9:8
match re.captures(line) {
None => { return results; },
Some(caps) => {
for (name, value) in caps.iter_named() {
if let Some(value) = value {
results.insert(name, value);
...
但是,我不明白.在这种情况下,regex::Regex::captures
return value has a lifetime of 't
, which is the same lifetime as the string表示’a’,即regex::Captures::iter_named
returned value also has the same lifetime of 't
,在这种情况下是’a’,这意味着(name, value)
for that thing也应该是’t,在这种情况下是’a.
我的函数定义有一个使用’生命周期的HashMap,所以不应该只是Just Work(tm)吗?我想我明白为什么你不能使用局部变量,除非你返回它,但在这种情况下,我使用的引用应该活得足够长,对吧?
我想我可以.clone()把所有东西都变成String,但我很好奇我是否可以用引用来编写它.那不应该更高效吗?我对Rust有点新意,所以我试图以适当,先进的方式处理事情并做事.
最佳答案 你的推理是正确的,但你忘记了一个细节:
regex::Regex::captures
return value has a lifetime of't
, which is the same lifetime as the string, in this case, that means'a
, theregex::Captures::iter_named
* returned value also has the same lifetime of't
, which is'a
in this case, and that means the(name, value)
for that thing should also be't
, which in this case is'a
.
* regex :: Captures :: iter_named也需要一个自我,也就是说,& caps必须有生命周期’t'(在这种情况下为’a).
请注意,编译器不是抱怨结果而是抱怨大写. regex :: Regex :: capture返回上限:Captures<‘a> ;,这意味着上限保留了一些生命周期’a.但是要调用regex :: Captures :: iter_named,必须有一个带有生命周期’的参考(iter_named参数是&’a self =&’a Captures<‘a>).虽然大写字母持有生命周期’a’,但它没有生命周期’a(生命周期只有Some arm).
我不知道iter_named如何使用空名称处理捕获,但这里是一个只返回命名捕获的实现:
extern crate regex;
use std::collections::HashMap;
use regex::Regex;
fn get_matches<'a>(line: &'a str, re: &'a Regex) -> HashMap<&'a str, &'a str> {
let mut results = HashMap::new();
match re.captures(line) {
None => {
return results;
}
Some(caps) => {
for name in re.capture_names() {
if let Some(name) = name {
if let Some(value) = caps.name(name) {
results.insert(name, value);
}
}
}
}
}
results
}
这可能比iter_named慢.