我一直在遇到问题而且我不太明白为什么不会编译这个:
fn foo(bar: &'static str) -> Foo {
let caps_off = bar.to_ascii_lower().as_slice();
...
}
错误:borrowed value does not live long enough
我有点理解这里的错误,但我不知道其他任何方法来实现这一点。
我尝试将str
转换为小写&然后将其转换回str
类型。看似简单。
我在这里做错了什么?我该如何解决?
完整代码:
use std::collections::HashMap;
use std::ascii::StrAsciiExt;
struct Foo;
fn foo(bar: &'static str) -> Foo {
let caps_off_ = bar.to_ascii_lower();
let caps_off = caps_off_.as_slice();
let mut my_foos:HashMap<&'static str, Foo> = HashMap::new();
my_foos.insert("hi", Foo);
*my_foos.find(&caps_off).clone().unwrap()
}
答案 0 :(得分:2)
由于编译器推断出的信息,错误很难理解。
caps_off
的类型是什么?您没有指定它,因此编译器必须根据其用法推断它。在这个表达式中只使用一次
*my_foos.find(&caps_off).clone().unwrap()
find
method上的Map
trait指定参数的类型为&K
。您将地图定义为HashMap<&'static str, Foo>
,因此K
为&'static str
。因此,参数的具体类型为&&'static str
。参数是&caps_off
,因此您正在构建引用。编译器推断caps_off
必须是&'static str
类型才能匹配参数的类型。这就是问题所在。
错误告诉您caps_off_.as_slice()
无法分配给caps_off
,因为借用的切片活动时间不够长。这是因为bar.to_ascii_lower()
返回String
,并且该字符串仅在函数调用期间存在。这意味着您无法将Map.find()
与此值一起使用。
幸运的是,HashMap
上有另一种解决问题的方法:find_equiv
。通过使用它,编译器可以推断出与您尝试分配给它的表达式(caps_off
)兼容的&'a str
的不同类型。只需更改foo
中的最后一行即可使用它:
*my_foos.find_equiv(&caps_off).clone().unwrap()
事实上,您甚至不需要致电as_slice()
,您可以直接传递String
返回的bar.to_ascii_lower()
,如果您不需要定义变量只使用小写字符串一次:
*my_foos.find_equiv(&bar.to_ascii_lower()).clone().unwrap()
答案 1 :(得分:0)
您应该发布完整的代码以便我们理解错误,但在该代码中,编译器无法判断新字符串的存在时间。 所以尝试:
fn foo(bar: &'static str) -> Foo {
let caps_off_ = bar.to_ascii_lower();
let caps_off = caps_off_.as_slice();
...
}
所以caps_off_
在您使用切片时保留新的String
对象。
编辑:
添加到上一个答案,弗朗西斯如何解释,你宣称地图的密钥是&'static str
,所以find
不会接受一个没有&#39}的密钥。 t匹配相同的签名。所以你有两个选择1)将地图声明为<&str, Foo>
而没有静态生命周期或2)使用find_equiv
方法。
希望它有所帮助。