如何将(String,String)元组上的Iterator转换为(& str,& str)的迭代器? [英] How to convert an Iterator on a tuple of (String, String) to an Iterator of (&str, &str)?
问题描述
我无法从(String, String)
的迭代器转换为(&str, &str)
的迭代器.我使用的是外部库,因此无法更改其签名,并且不确定是否需要这样做.基本上我有这个功能def:
I'm having trouble converting from an Iterator of (String, String)
to an Iterator of (&str, &str)
. I'm using an external library, so can't change the signature of that, and not sure that I need to. Basically I have this function def:
use hyper;
fn build_url<'a, I>(host: &'a str, port: u16, path: &'a str, params: I) ->
hyper::Url where I: Iterator<Item=(String, String)> {
let mut url = hyper::Url::parse(&format!("http://{h}:{p}/{pt}",
h = self.etcd_host,
p = self.etcd_port,
pt = path));
if let Err(e) = url {
panic!("error parsing url: {}", e);
}
let mut url = url.unwrap();
// fn set_query_from_pairs<'a, I>(&mut self, pairs: I)
// where I: Iterator<Item=(&'a str, &'a str)>
url.set_query_from_pairs(
params.map(|x: (String, String)| ->
(&str, &str) { let (ref k, ref v) = x; (k, v) } ));
}
但是我很害怕:error: 'x.0' does not live long enough
我认为let中的ref
关键字在这里应该是正确的事情,即,保留Iterator的所有权,并进行借用.如果我在将let更改为let的过程中摆脱了ref
的话,也会遇到类似的问题:
I think the ref
keyword in the let should have been the right thing here, i.e. keep the ownership with the Iterator, and just do a borrow. I get a similar issue if I get rid of ref
in the let changing the let to this:
let (k, v) = x; (&k, &v)
然后k
和v
的寿命不足.有没有人建议解决此问题?
Then k
and v
don't live long enough. Does anyone have a recommendation for fixing this?
推荐答案
您不能拥有(安全地)产生对任何内部或拥有状态的引用的迭代器; Iterator
特质并非旨在允许它.这种构造通常称为流式迭代器",目前在语言/stdlib中是一个漏洞.
You can't have an iterator that (safely) yields references to any internal or owned state; the Iterator
trait is just not designed to allow it. These sorts of constructs are usually known as "streaming iterators", and they're something of a hole in the language/stdlib at the moment.
考虑(String, String)
值在您的map
调用中流动时会发生什么.每个元组都从I::next
返回,这导致所有权传递到您给map
的闭包中.因此,当在闭包中使用ref
时,您将引用对闭包本地的变量 .现在,您构造一个新的元组,将其返回并...因为该闭包拥有String
(它们存储在k
和v
中),它们已被销毁,从而使您尝试返回的引用无效
Consider what happens to a (String, String)
value as it flows through your map
call. Each tuple is returned from I::next
, which causes ownership to pass into the closure you gave to map
. Thus, when you use ref
in the closure, you're taking a reference to variables which are local to the closure. You now construct a new tuple, return it and... because the closure owns the String
s (they're being stored in k
and v
), they are destroyed, thus invalidating the references you tried to return.
问题在于,没有办法避免获得对(String, String)
项的所有权.
The problem is that there is no way to avoid taking ownership of the (String, String)
items.
现在,话虽如此,您可以在这里作弊.您需要做的就是确保(String, String)
值在迭代器的每个单独步骤之后都继续存在.因此:
Now, that having been said, you can cheat here. All you need to do is guarantee that the (String, String)
values continue to exist beyond each individual step in the iterator. Thus:
let params: Vec<_> = params.collect();
url.set_query_from_pairs(params.iter().map(|&(ref x, ref y)| (&x[..], &y[..])))
之所以可行,是因为Vec::iter
给了我们Iterator<Item=&(String, String)>
,我们可以从中借用 而无需拥有所有权(由
This works because Vec::iter
gives us Iterator<Item=&(String, String)>
, from which we can borrow without taking ownership (which is retained by params
).
这篇关于如何将(String,String)元组上的Iterator转换为(& str,& str)的迭代器?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!