How to fix this ownership error: cannot move out of index - rust

I am trying to move ownership of structure from "children" to "genomes" in the thread of "create_next_generation", Because part of genomes should be the same value of children, and then the children would be never used. This is the code of the process that indicates the context.
fn create_next_generation<'a>(genomes: &'a mut Vec<Genome>,
children: Vec<Genome>, gene_mutate: f32, individual_mutate: f32, survive_number: usize){
for i in survive_number..children.len(){
genomes[i] = children[i-survive_number]; //<--------error
}
}
fn main() {
let mut genome_list: Vec<Genome> = Vec::new();
.
.
.
let mut children: Vec<Genome> = Vec::new();
.
.
.
create_next_generation(&mut genome_list, children, values.genome_mutation,
values.individual_mutation, values.select_genome)
}
and the structure is
struct Genome{
dna : Vec<i32>,
eval : f64,
}
The error is
error[E0507]: cannot move out of index of `Vec<Genome>`
--> src/main.rs:109:26
|
109 | genomes[i] = children[i-survive_number];
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ move occurs because value has type `Genome`, which does not implement the `Copy` trait
How can I fix this problem?

Moving is not allowed in this case -- you can only move an owned value, but the value you're trying to move here is owned by the children vector. You could make this work with std::mem::take() (if Genome implements Default), but there's an even easier way to handle this: Vec::splice().
The splice operation returns an iterator over a range of elements to be removed from the vector, producing them by moving instead of copying. It doesn't matter too much that the vector is modified since it will be destroyed anyway, but this gives you a simple way to move a bunch of elements out of the vector in a single mutating operation.
Chaining this with .enumerate() gives us the index of each element (starting with 0).
for (i, v) in children.splice(survive_number..).enumerate() {
genomes[i] = v;
}
It's unclear if you want to replace genomes entirely with these removed elements, but if that's the case then this operation becomes a one-liner:
*genomes = children.splice(survive_number..).collect();
Since you are destroying the vector anyway, you could even use children.into_iter().skip(survive_number) in place of children.splice(survive_number..) in the above examples, which will consume the vector.

Related

How to rotate a linked list in Rust?

I came across a leetcode example https://leetcode.com/problems/rotate-list/ and wanted to implement it in Rust but I keep moving out of my variables. For instance if I use head to track down the end of the list I cannot move its value to the last next because it is already moved out of the variable. How should I think to avoid this kind of problems?
And this is my attempt in rust
// Definition for singly-linked list.
#[derive(PartialEq, Eq, Clone, Debug)]
pub struct ListNode {
pub val: i32,
pub next: Option<Box<ListNode>>,
}
impl ListNode {
#[inline]
fn new(val: i32) -> Self {
ListNode { next: None, val }
}
}
pub fn rotate_right(head: Option<Box<ListNode>>, k: i32) -> Option<Box<ListNode>> {
if k == 0 {
return head;
}
let mut len = 0;
let mut curr = &head;
while let Some(n) = curr {
curr = &n.next;
len += 1;
}
drop(curr);
let newk = len - ( k % len);
println!("Rotate {} right is {} mod {}",k,newk,len);
let mut node = head.as_ref();
for _i in 0..newk {
if let Some(n) = node {
node = n.next.as_ref();
}else {
println!("Unexpected asswer fail");
}
}
let mut newhead = None ;// node.unwrap().next; // node will be last and newhead will be first.
if let Some(mut n) = node{ // node should have a value here
newhead = n.next;
n.next = None
}
drop(node);
let node = newhead;
if let Some(c) = node{
let mut curr = c;
while let Some(next) = curr.next {
curr = next;
}
curr.next = head;
newhead
}else{
println! ("Todo handle this corner case");
None
}
}
But this yields errors about moving and use of borrowed references.
error[E0507]: cannot move out of `n.next` which is behind a shared reference
--> src/main.rs:99:23
|
99 | newhead = n.next;
| ^^^^^^
| |
| move occurs because `n.next` has type `Option<Box<ListNode>>`, which does not implement the `Copy` trait
| help: consider borrowing the `Option`'s content: `n.next.as_ref()`
error[E0594]: cannot assign to `n.next` which is behind a `&` reference
--> src/main.rs:100:13
|
98 | if let Some(mut n) = node{ // node should have a value here
| ----- help: consider changing this to be a mutable reference: `&mut Box<ListNode>`
99 | newhead = n.next;
100 | n.next = None
| ^^^^^^ `n` is a `&` reference, so the data it refers to cannot be written
error[E0382]: use of moved value: `newhead`
--> src/main.rs:111:13
|
97 | let mut newhead = None ;// node.unwrap().next; // node will be last and newhead will be first.
| ----------- move occurs because `newhead` has type `Option<Box<ListNode>>`, which does not implement the `Copy` trait
...
104 | let node = newhead;
| ------- value moved here
...
111 | newhead
| ^^^^^^^ value used here after move
Finlay this is reference code in c of what I intended it to look like:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* rotateRight(struct ListNode* head, int k){
struct ListNode* node = head;
int len = 1;
if (k == 0 || !head){
return head;
}
while (node->next){
node = node->next;
len++;
}
int newk = len - (k % len) -1;
node = head;
while (newk--){
if (node->next) {
node = node->next;
}
}
if ( !node->next) {
return head; // do not move anything
}
struct ListNode* newhead = node->next; // node will be last and newhead will be first.
struct ListNode* n = node->next;
node->next = 0;
node = n;
while (node->next != 0) {
node = node->next;
}
node->next = head;
return newhead;
}
So my question is what technique can be used to avoid this move use trap?
I'd like to preface this post by saying that this type of Linked List in Rust is not a particularly good representation. Unfortunately, safe Rust's ownership model makes reference chain structures such as Linked Lists problematic and hard to reason about for any more than simple operations, despite Linked Lists being very simple in other languages. While for beginners, simple but inefficient implementations of simple concepts are often important and useful, I would also like to emphasize that the safe Rust "sentinel model" for trees and linked lists also has a heavy performance cost. Learning Rust With Entirely Too Many Linked Lists is the de facto book for learning how to properly deal with these structures, and I recommend it to all beginners and intermediate Rust programmers who haven't worked through it (or at least skimmed it).
However, this particular operation is possible on sentinel model singly linked lists in purely safe Rust. The whole version of the code I'm about to present is available on the Playground, which includes some things like test cases and an iterator implementation I'll be glossing over (since it doesn't get to the core of the problem and is only used in test cases and to derive the entire size of the Linked List). I also won't be presenting the ListNode struct or the new function, since they are in the question itself. Note that I also took some design liberties (instead of a free function, I made rotate_right and rotate_left member functions, you can freely convert but this is more Rusty design).
The "obvious' implementation here is to drain the entire list and reconstruct it. This is a perfectly good solution! However it's likely inefficient (it can be more or less inefficient depending on whether you totally destroy the nodes or not). Instead we're going to be doing what you largely do in other languages: only breaking the link and then reassigning the pointers at the boundaries. In fact, once you break it down into these two steps, the problem becomes much easier! All that's required is knowledge about Rust's mutable borrowing semantics, and how to overcome the pesky requirement that references always have a definite value and cannot be moved out of.
1. Breaking the Link: mutable reference uniqueness & memory integrity
/// Splits the list at a given index, returning the new split off tail.
/// Self remains unmodified.
/// The list is zero indexed, so,
/// for instance, a value of 2 in the list [1,2,3,4,5]
/// will cause self to be [1,2,3] and the return value to be
/// Some([4,5]). I.E. the link is "broken" AT index 2.
///
/// If there's nothing to split off, `None` is returned.
fn split_at(&mut self, n: usize) -> Option<Self> {
use std::mem;
let mut split = Some(self);
for _ in 0..n {
if let Some(node) = split.map(|v| v.next.as_deref_mut()) {
split = node;
} else {
return None;
}
}
match split {
Some(node) => {
let mut new_head = None;
mem::swap(&mut new_head, &mut node.next);
new_head.map(|v| *v)
}
None => None
}
}
The logic is straightforward (if you've broken off a list in any other language it's the exact same algorithm). The important thing for Rust is the ownership system and the mem::swap function. Rust ensures two things that are problematic here:
You're not mutably borrowing the same thing twice.
No piece of memory is invalid, even temporarily (particularly in self).
For 1., we use the code
if let Some(node) = split.map(|v| v.next.as_deref_mut()) {
split = node;
}
What this does is simply advances the pointer, making sure to immediately "forget" our current mutable pointer, and never do anything that directly causes "self" to be used at the same time as "node". (Note that if you tried this in an earlier version of Rust, I don't believe this was possible before Non-Lexical Lifetimes (NLLs), I think it would both alias self and node under the old rules). The map is simply to allow us to reassign to split by "reborrowing" the inner Box as an actual reference, so we can recycle the seed variable we start as self (since you can't reassign self in this way).
For solving 2. we use:
match split {
Some(node) => {
let mut new_head = None;
mem::swap(&mut new_head, &mut node.next);
new_head.map(|v| *v)
}
None => None
}
The key here is the mem::swap line. Without this Rust will complain about you moving node.next. Safe Rust requires you to ensure there is always a value in every variable. The only exception is if you're permanently destroying a value, which doesn't work on references. I think there's some QOL work on the compiler at the moment to allow you to move out of a mutable reference if you immediately put something in its place and the compiler can prove there will be no panic or return between these operations (i.e. memory cannot become corrupted during a stack unwind), but as of Rust 1.47 this is not available.
2. Stitching the list back together: memory integrity
/// Attaches the linked list `new_tail` to the end
/// of `self`. For instance
/// `[1,2,3]` and `[4,5]` will make self a list containing
/// `[1,2,3,4,5]`.
fn extend_from_list(&mut self, new_tail: ListNode) {
let mut tail = self;
while tail.next.is_some() {
tail = tail.next.as_deref_mut().unwrap();
}
tail.next = Some(Box::new(new_tail))
}
This method isn't too complicated, it just assigns the next reference to the head node of the passed in list. If you've written a function to attach a new node it's functionally the same. Again, the key is that we advance the pointer to the end, being very careful we never allow a mutable reference to alias, which allows us to appease the Borrow Checker.
From there, we can finish up!
/// Rotates the list `k` elements left. So
/// `[1,2,3]` rotated 2 left is `[3,1,2]`.
///
/// The function handles rotating an arbitrary number of steps
/// (i.e. rotating a size 3 list by 5 is the same as rotating by 2).
fn rotate_left(&mut self, k: usize) {
use std::mem;
let k = k % self.iter().count();
if k == 0 {
return;
}
let k = k-1;
if let Some(mut new_head) = self.split_at(k) {
mem::swap(self, &mut new_head);
let new_tail = new_head;
self.extend_from_list(new_tail);
} else {
unreachable!("We should handle this with the mod!")
}
}
/// Rotates the list `k` elements right. So
/// `[1,2,3]` rotated 2 right is `[2,3,1]`.
///
/// The function handles rotating an arbitrary number of steps
/// (i.e. rotating a size 3 list by 5 is the same as rotating by 2).
fn rotate_right(&mut self, k: usize) {
self.rotate_left(self.iter().count() - k)
}
Rotating left is conceptually easiest, since it's just splitting a list at the given index (k-1 because to rotate k places we need to break the link after counting one fewer indices). Again, we need to make use of mem::swap, the only tricky thing about this code, because the part we split off is the new head and Rust won't let us use temp variables due to the memory integrity guarantee.
Also, it turns out rotating right k places is just rotating left size-k places, and is much easier to conceptualize that way.
This is all somewhat inefficient though because we're marching to the end of the list each time (particularly for the list fusion), because we're not holding onto the tail pointer and instead re-iterating. I'm fairly certain you can fix this, but it may be easier to make it one large function instead of sub-functions, since returning a downstream tail pointer would require some lifetime flagging. I think if you want to take a next step (besides the Linked List book, which is probably a better use of your time), it would be good to see if you can preserve the tail pointer to eliminate the constant marching down the list.

Immutable access in rust

I am new to rust from python and have used the functional style in python extensively.
What I am trying to do is to take in a string (slice) (or any iterable) and iterate with a reference to the current index and the next index. Here is my attempt:
fn main() {
// intentionally immutable, this should not change
let x = "this is a
multiline string
with more
then 3 lines.";
// initialize multiple (mutable) iterators over the slice
let mut lineiter = x.chars();
let mut afteriter = x.chars();
// to have some reason to do this
afteriter.skip(1);
// zip them together, comparing the current line with the next line
let mut zipped = lineiter.zip(afteriter);
for (char1, char2) in zipped {
println!("{:?} {:?}", char1, char2);
}
}
I think it should be possible to get different iterators that have different positions in the slice but are referring to the same parts of memory without having to copy the string, but the error I get is as follows:
error[E0382]: use of moved value: `afteriter`
--> /home/alex/Documents/projects/simple-game-solver/src/src.rs:15:35
|
10 | let afteriter = x.chars();
| --------- move occurs because `afteriter` has type `std::str::Chars<'_>`, which does not implement the `Copy` trait
11 | // to have some reason to do this
12 | afteriter.skip(1);
| --------- value moved here
...
15 | let mut zipped = lineiter.zip(afteriter);
| ^^^^^^^^^ value used here after move
I also get a warning telling me that zipped does not need to be mutable.
Is it possible to instantiate multiple iterators over a single variable and if so how can it be done?
Is it possible to instantiate multiple iterators over a single variable and if so how can it be done?
If you check the signature and documentation for Iterator::skip:
fn skip(self, n: usize) -> Skip<Self>
Creates an iterator that skips the first n elements.
After they have been consumed, the rest of the elements are yielded. Rather than overriding this method directly, instead override the nth method.
You can see that it takes self by value (consumes the input iterator) and returns a new iterator. This is not a method which consumes the first n elements of the iterator in-place, it's one which converts the existing iterator into one which skips the first n elements.
So instead of:
let mut afteriter = x.chars();
afteriter.skip(1);
you just write:
let mut afteriter = x.chars().skip(1);
I also get a warning telling me that zipped does not need to be mutable.
That's because Rust for loop uses the IntoIterator trait, which moves the iterable into the loop. It's not creating a mutable reference, it's just consuming whatever the RHS is.
Therefore it doesn't care what the mutability of the variable. You do need mut if you iterate explicitly, or if you call some other "terminal" method (e.g. nth or try_fold or all), or if you want to iterate on the mutable reference (that's mostly useful for collections though), but not to hand off iterators to some other combinator method, or to a for loop.
A for loop takes self, if you will. Just as for_each does in fact.
Thanks to #Stargateur for giving me the solution. The .skip(1) takes ownership of afteriter and returns ownership to a version without the first element. What was happening before was ownership was lost on the .skip and so the variable could not be mutated anymore (I am pretty sure)

Why do I get "no method named push found for type Option" with a vector of vectors?

I tried to use a String vector inside another vector:
let example: Vec<Vec<String>> = Vec::new();
for _number in 1..10 {
let mut temp: Vec<String> = Vec::new();
example.push(temp);
}
I should have 10 empty String vectors inside my vector, but:
example.get(0).push(String::from("test"));
fails with
error[E0599]: no method named `push` found for type `std::option::Option<&std::vec::Vec<std::string::String>>` in the current scope
--> src/main.rs:9:20
|
9 | example.get(0).push(String::from("test"));
| ^^^^
Why does it fail? Is it even possible to have an vector "inception"?
I highly recommend reading the documentation of types and methods before you use them. At the very least, look at the function's signature. For slice::get:
pub fn get<I>(&self, index: I) -> Option<&<I as SliceIndex<[T]>>::Output>
where
I: SliceIndex<[T]>,
While there's some generics happening here, the important part is that the return type is an Option. An Option<Vec> is not a Vec.
Refer back to The Rust Programming Language's chapter on enums for more information about enums, including Option and Result. If you wish to continue using the semantics of get, you will need to:
Switch to get_mut as you want to mutate the inner vector.
Make example mutable.
Handle the case where the indexed value is missing. Here I use an if let.
let mut example: Vec<_> = std::iter::repeat_with(Vec::new).take(10).collect();
if let Some(v) = example.get_mut(0) {
v.push(String::from("test"));
}
If you want to kill the program if the value is not present at the index, the shortest thing is to use the index syntax []:
example[0].push(String::from("test"));

Iterating through a Vec within a struct - cannot move out of borrowed content

I am writing a function for a struct which contains a Vec where I attempt to iterate through the Vec:
struct Object {
pub v: Vec<f32>,
}
impl Object {
pub fn sum(&self) -> f32 {
let mut sum = 0.0;
for e in self.v {
sum += e;
}
sum
}
}
However I get the following error:
error[E0507]: cannot move out of borrowed content
--> src/lib.rs:8:18
|
8 | for e in self.v {
| ^^^^ cannot move out of borrowed content
My understanding is that since self is borrowed and that the for loop iteration is attempting to move the elements of v out into e.
From the error code, I read that a potential solution is to take ownership but I'm not quite certain how to do that.
I'm not trying to modify the vector or its elements. I just want to use the elements to run some computation.
The line: for e in self.v is essentially saying for e in (*self).v; you're attempting to iterate over the vector by move, invoking its IntoIterator trait. This would destroy the vector completely, moving all the numbers out of it forever, which is not only not what you want, but also not allowed in this context because you're only allowed to read it.
You actually want to iterate over it by reference. There are two ways to do this:
for e in &self.v {
// ...
}
This is essentially saying &((*self).v), since the . auto-dereferences you need to tell the compiler that you actually just want to borrow the vector.
or
for e in self.v.iter() {
// ...
}
This may look funny because iter takes an &self. Why? Well, the compiler also auto-references if you call a function on a value that takes a reference. This is essentially (&((*self).v)).iter(), but that would suck to write so the compiler helps out.
So why doesn't it auto-reference in the for loop? Well, for x in self.v is a valid statement, and that may be what you intended to write. It's usually more important for the compiler to tell you that what you want want is impossible than assume you wanted something else. With the auto (de-)referencing above, no such ambiguity exists.
The former solution is preferred, but the latter is necessary if you want to use an iterator adapter.
Speaking of which, your sum already exists: just write self.v.iter().sum().

Is there an elegant solution to modifying a structure while iterating?

I'm trying to build a vector of points that are changed while iterating over them:
struct Point {
x: i16,
y: i16,
}
fn main() {
let mut points: Vec<Point> = vec![];
// unsure if point is mutable
points.push(Point { x: 10, y: 10 });
// thus trying it explicitly
let mut p1 = Point { x: 20, y: 20 };
points.push(p1);
for i in points.iter() {
println!("{}", i.x);
i.x = i.x + 10;
}
}
When compiling, I get the error:
error[E0594]: cannot assign to immutable field `i.x`
--> src/main.rs:16:9
|
16 | i.x = i.x + 10;
| ^^^^^^^^^^^^^^ cannot mutably borrow immutable field
As I learned here, Rust doesn't allow modifying the structure while iterating over it, thus the error.
How do I modify it in an elegant way? If I read this answer and get it right then the following comes to my mind:
pop the item from the vector, modify it and push it back.
create a temporary structure where I push the changed items to and replace original structure with the temporary one outside the loop (how?).
While I think I can get (1) working, I'm not really happy about all this pop's and push's (is this high-performance anyhow?). Concerning (2), I have no idea how to get it working - if this would work at all.
Questions:
Is (2) an solution and if yes, how would it look like?
Are there any other solutions?
What's the advantage or disadvantage of the different solutions, especially with respect to performance?
You cannot modify the structure you are iterating over, that is, the vector points. However, modifying the elements that you get from the iterator is completely unproblematic, you just have to opt into mutability:
for i in points.iter_mut() {
Or, with more modern syntax:
for i in &mut points {
Mutability is opt-in because iterating mutably further restricts what you can do with points while iterating. Since mutable aliasing (i.e. two or more pointers to the same memory, at least one of which is &mut) is prohibited, you can't even read from points while the iter_mut() iterator is around.

Resources