I'm using Kuchiki to parse some HTML and making HTTP requests using hyper to concurrently operate on results through scoped_threadpool.
I select and iterate over listings. I decide the number of threads to allocate in the threadpool based on the number of listings:
let listings = document.select("table.listings").unwrap();
let mut pool = Pool::new(listings.count() as u32);
pool.scoped(|scope| {
for listing in listings {
do_stuff_with(listing);
}
});
When I try to do this I get capture of moved value: listings
. listings
is kuchiki::iter::Select<kuchiki::iter::Elements<kuchiki::iter::Descendants>>
, which is non-copyable -- so I get neither an implicit clone nor an explicit .clone
.
Inside the pool I can just do document.select("table.listings")
again and it will work, but this seems unnecessary to me since I already used it to get the count. I don't need listings
after the loop either.
Is there any way for me to use a non-copyable value in a closure?
Sadly, I think it's not possible the way you want to do it.
Your listings.count()
consumes the iterator listings
. You can avoid this by writing listings.by_ref().count()
, but this won't have the desired effect, since count()
will consume all elements of the iterator, so that the next call to next()
will always yield None
.
The only way to do achieve your goal is to somehow get the length of the iterator listings
without consuming its elements. The trait ExactSizeIterator
was built for this purpose, but it seems that kuchiki::iter::Select
doesn't implement it. Note that this may also be impossible for that kind of iterator.
Edit: As @delnan suggested, another possibility is of course to collect the iterator into a Vec
. This has some disadvantages, but may be a good idea in your case.
Let me also note, that you probably shouldn't create one thread for every line in the SELECT
result set. Usually threadpools use approximately as many threads as there are CPUs.