Home > Blockchain >  How to pass lines() iterator as an argument to a function, in a loop
How to pass lines() iterator as an argument to a function, in a loop

Time:10-09

Here is the beginning:

    let fb = BufReader::new(&f);
    let lines = fb.lines();

        let bank_sequence = read_1_sequence(&mut count, lines);
        print_seq(&bank_sequence);

and here the read_1_sequence function :

    fn read_1_sequence<B: BufRead>(count: &mut u8, lines: Lines<B>)
// ...

    for line in lines {
        let the_line = line.unwrap();
        if the_line.len() > 0 {
        let first = &the_line[0..1];
        if first == ">" {
// etc.

But, if the call to read_1_sequence is in a loop, like here:

    loop {
        let bank_sequence = read_1_sequence(&mut count, lines);
        print_seq(&bank_sequence);
    }

I receive (obviously) the message:

26 |     let lines = fb.lines();
   |         ----- move occurs because `lines` has type `std::io::Lines<BufReader<&File>>`, which does not implement the `Copy` trait
...
29 |         let bank_sequence = read_1_sequence(&mut count, lines);
   |                                                         ^^^^^ value moved here, in previous iteration of loop

Is there a solution? Thanks for any hint.

Have a nice (programming) day!

CodePudding user response:

The other answers suggest cloning lines, but that won't work because Lines doesn't implement Clone (and if it did, it would probably start over from the beginning of the file in each loop). Instead you should change your function to take &mut Lines<B>:

fn read_1_sequence<B: BufRead>(count: &mut u8, lines: &mut Lines<B>)

and call it like this:

loop {
    let bank_sequence = read_1_sequence(&mut count, &mut lines);
    print_seq(&bank_sequence);
}

CodePudding user response:

Use impl Iterator<Item=String>, so your functions can work over anything that implements the trait (which Lines implements iirc):

fn read_1_sequence<B: BufRead>(count: &mut u8, lines: impl Iterator<Item=String>) {
    ...
}

Also, you would need to clone the iterator in order to use it more than once.

CodePudding user response:

You have to use lines.clone() or declare read_1_sequence(.., lines: &Lines).

see exemple bellow

fn main()
{
    //Work because array implement Copy
    let a: [i32; 4] = [1,2,3,4];
    seq(a);
    seq(a);
    
    //Not work
    let b: Vec<i32> = [1,2,3,4].to_vec();
    seq2(b);
    seq2(b); // <--failed because Vec not implement Copy
    
    //Solution 1
    let c: Vec<i32> = [1,2,3,4].to_vec();
    seq2(c.clone());
    seq2(c.clone());
    //Solution 2
    seq3(&c);
    seq3(&c);
}

fn seq(lines: [i32; 4])
{
    for line in lines {
        println!("{}", line);
    }
}

fn seq2(lines: Vec<i32>)
{
    for line in lines {
        println!("{}", line);
    }
}

fn seq3(lines: &Vec<i32>)
{
    for line in lines {
        println!("{}", line);
    }
}
  • Related