如何将(String,String)元组上的Iterator转换为(& str,& str)的迭代器? [英] How to convert an Iterator on a tuple of (String, String) to an Iterator of (&str, &str)?

查看:95
本文介绍了如何将(String,String)元组上的Iterator转换为(& 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)

然后kv的寿命不足.有没有人建议解决此问题?

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(它们存储在kv中),它们已被销毁,从而使您尝试返回的引用无效

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 Strings (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转换为(&amp; str,&amp; str)的迭代器?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆