Std::mem::replace inside of macro not working?

Does noah has the following macro?

#[macro_export]
macro_rules! infinite {
    ($current:expr) => {{
        if let Some(cuschur) = $current.last() {
           if cuschur == &i8::MAX {
               $current.push(0); 
           } else {
               std::mem::replace(&mut $current[$current.len() - 1], cuschur + 1);
           }
        }
        $current
    }}
}

is the point of the macro to increase the value of i8 in reality i128 with an vector?
why is mem::replace not working?
how to accomplish the same?

I have no idea what your question is, but it does not make sense to use std::mem::replace if you are not using its return value.

fn main () {
    let mut current = vec![1, 2, 3, 126];
    
    if let Some(cuschur) = current.last() {
       if cuschur == &i8::MAX {
           current.push(0); 
       } else {
           std::mem::replace(&mut current[current.len() - 1], cuschur + 1);
       }
    }
    dbg!(current);
}

tells you

error[E0502]: cannot borrow `current` as mutable because it is also borrowed as immutable
  --> src/main.rs:21:35
   |
17 |     if let Some(cuschur) = current.last() {
   |                            ------- immutable borrow occurs here
...
21 |            std::mem::replace(&mut current[current.len() - 1], cuschur + 1);
   |                                   ^^^^^^^                     ------- immutable borrow later used here
   |                                   |
   |                                   mutable borrow occurs here

error[E0502]: cannot borrow `current` as immutable because it is also borrowed as mutable
  --> src/main.rs:21:43
   |
21 |            std::mem::replace(&mut current[current.len() - 1], cuschur + 1);
   |                                   --------^^^^^^^-----------
   |                                   |       |
   |                                   |       immutable borrow occurs here
   |                                   mutable borrow occurs here
   |                                   mutable borrow later used here

So it does not work because you try to read $current and modify it in the same expression. I think the root problem here is that you try to access the last element twice (once with last, once with [cuschur.len() - 1]).
A fixed and easier version would be:

fn main () {
    let mut current = vec![1, 2, 3, 126];
    
    if let Some(cuschur) = current.last_mut() {
        if cuschur == &i8::MAX {
           current.push(0);
        } else {
           *cuschur += 1;
        }
    }
    dbg!(current);
}

or as a macro:

macro_rules! infinite {
    ($current:expr) => {{
        if let Some(cuschur) = $current.last_mut() {
           if cuschur == &i8::MAX {
               $current.push(0); 
           } else {
               *cuschur += 1;
           }
        }
        $current
    }}
}

last_mut allows you to modify the last element without reindexing the array.

Also, mem::replace is not really useful here, because you're not using the old value, so assignation just works

1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.