2

TLDR

How to make the following code compile?

let mut iter = (1..3).peekable();
let h = iter.peek();
iter.next();

Update: I read How to use Rust's Peekable?, that is a different question because

  1. I don't even have a function here
  2. I don't have move out of dereference of error here

Long Story With Background

I'm trying to implement merging of two sorted "streams": I have two iterators both of which produce ordered values, and I need to print values of both of them, also ordered.

For example,

(1, 2, 20)
(3, 4, 5, 7)

should produce

(1, 2, 3, 4, 5, 7, 20)

The algorithm is simple I compare heads, then print the smaller head and advance the corresponding iterator.

The problem is that I can't wrap my head around lifetimes.

I have some initial implementation which isn't compiling. In order to make my question simpler to answer, I reduced my original implementation to the smallest possible example which fails with the same error as the original.

let mut iter = (1..3).peekable();
let h = iter.peek();
iter.next();

The error is

error[E0499]: cannot borrow `iter` as mutable more than once at a time
   --> src/main.rs:47:9
    |
44  |         let h = iter.peek();
    |                 ---- first mutable borrow occurs here
...
47  |         iter.next();
    |         ^^^^ second mutable borrow occurs here
...
114 | }
    | - first borrow ends here

How to fix this error?

I tried to do different things: adding mut, &, .by_ref() everywhere, but obviously, it didn't work because I have no idea what I'm doing.

DNNX
  • 6,215
  • 2
  • 27
  • 33
  • *I also read a bunch of articles and answers to other similar questions here at StackOverflow, but it didn't help.* — **which** did you read, **why** didn't they help? If you don't tell us, then what prevents an answerer from stating the exact same thing you've already read, wasting your time and theirs? – Shepmaster Jan 05 '18 at 18:40
  • 1
    https://play.rust-lang.org/?gist=ca6e6e2bf6dda402b34d5fe0f26658e1&version=stable ? Your [mcve] is maybe too simple ;) – Stargateur Jan 05 '18 at 18:44
  • 1
    See also: https://stackoverflow.com/q/26920789/155423; https://stackoverflow.com/q/23969191/155423; https://stackoverflow.com/q/37508081/155423. – Shepmaster Jan 05 '18 at 18:44
  • 1
    [`itertools::merge`](https://docs.rs/itertools/0.7.4/itertools/fn.merge.html) has already implemented this functionality. – Shepmaster Jan 05 '18 at 18:48
  • Oh wow, that's awesome. Thanks @Shepmaster! – DNNX Jan 05 '18 at 18:51
  • 1
    @Shepmaster may I ask what search queries did you use to find those posts? – DNNX Jan 05 '18 at 19:04
  • 1
    [site:stackoverflow.com rust mutable more than once at a time peekable](https://www.google.com/search?q=site:stackoverflow.com%20rust%20mutable%20more%20than%20once%20at%20a%20time%20peekable) and [site:stackoverflow.com rust mutable more than once at a time iterator](https://www.google.com/search?q=site%3Astackoverflow.com+rust+mutable+more+than+once+at+a+time+iterator) — a part of the error message without the variable name in it and then "peekable" and widening out to "iterator". – Shepmaster Jan 05 '18 at 19:09
  • What should I do with the question now that it's answered? – DNNX Jan 05 '18 at 19:27
  • 2
    @DNNX: If your answer is in one of the linked questions, please tell us which and we can vote to close as duplicate. If it's the `itertools::merge`, it would be really nice if you answered the question yourself citing the tool and exposing why it works (hint: it uses two phases, first comparing then releasing the borrows, then advancing the right iterator). For bonus points, you can try and implement it for an arbitrary number of iterators (hint: use a heap for efficiency). – Matthieu M. Jan 05 '18 at 19:55

1 Answers1

1

The Option::cloned(&self) method turns an Option<&T> into a Option<T>, given that T:Clone. It gets rid of the reference by making a copy of the value.

let mut iter = (1..3).peekable();
let h = iter.peek().cloned();
iter.next();
NovaDenizen
  • 5,089
  • 14
  • 28
  • Solving someones problem only enables them to get over that single problem. Explaining why the problem exists and the general approach to solving it will go a lot further. – Shepmaster Jan 06 '18 at 01:07
  • 1
    Sometimes monkey-see monkey-do is the best way to learn. We learn by imitation. – NovaDenizen Jan 06 '18 at 01:25