News for hackers. Stuff that matters.
Re:My favorite Rust function by AlanSE on Saturday October 12, 2019 @07:43PM (#21237149)
What do you mean by "will not work"? Will it not compile? And how do we write that with add1 taking ownership vs. not?
Re:My favorite Rust function by Filligree on Saturday October 12, 2019 @07:50PM (#21237176)
You'll get a compile-time error explaining the situation, yes, including documentation links and possible fixes. The differences between the versions are minimal.

    fn add1(x: Thing) -> Thing {
      x + 1
    }

    fn add2(x: &Thing) -> Thing {
      x + 2
    }
This works on the assumption that whatever "+ 1" really means doesn't itself need ownership of x, e.g. because it mutates it. If it does, then you'll get an error. Or you could do this:

    fn add3(x: &mut Thing) {
      x.add(3)
    }
Which, presumably, modifies x instead of returning a copy. It's your job to make sure it makes sense to do that, but Rust has another trick in its pockets:

    let y = add1(x);  // Works; takes ownership.
    let z = add2(&y);  // Works, and doesn't take ownership.
    let zz = add2(&y);  // So you can do it twice. (Y tho?)
    let h = add3(&y);  // Compile-time error!
    let hh = add3(&mut y);  // Works. You need to specify that you're fine with y being mutated.
Re:My favorite Rust function by saagarjha on Saturday October 12, 2019 @07:55PM (#21237202)
Consider the following code:

  fn add1(x: Vec<i32>) -> Vec<i32> { // Takes ownership
      return x.iter().map(|&x| x + 1).collect::<Vec<_>>();
  }
  
  fn add1_borrow(x: &Vec<i32>) -> Vec<i32> {
      return x.iter().map(|&x| x + 1).collect::<Vec<_>>();
  }
The first will take ownership of the thing you pass in, so you can't do something like this:

  let x = vec![1, 2, 3];
  let y = add1(x);
  let z = add1(x); // error[E0382]: use of moved value: `x`
but the follow code is OK, because the function just borrows the value instead of owning (and destroying) it:

  let x = vec![1, 2, 3];
  let y = add1_borrow(&x);
  let z = add1_borrow(&x);
This is legal too:

  let x = vec![1, 2, 3];
  let y = add1_borrow(&x);
  let z = add1(x);
but as before you can't use x after this.

(Note, I chose Vec here because Vec does not implement Copy: if I used i32 it would just copy the value in the non-borrowing case, which would make the code fine as no ownership would be transferred.)

Re:My favorite Rust function by db48x on Saturday October 12, 2019 @07:49PM (#21237174)
It won't compile, because the compiler keeps track of where you moved the value and notices that x now has no value. If you want the function to borrow the argument instead, make it take a reference, &x.