How to assign to a slice range? [duplicate] - rust

This question already has answers here:
How do you copy between arrays of different sizes in Rust?
(3 answers)
Closed 1 year ago.
I have a mutable slice, and I want to replace its prefix if it equals a certain slice.
I tried this:
let len = prefix.len();
if slice.starts_with(prefix) {
slice[.. len - 1] = subst;
}
Playground
However,
error[E0277]: the size for values of type `[{integer}]` cannot be known at compilation time
--> src/main.rs:13:9
|
13 | slice[.. len - 1] = *subst;
| ^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
(Let's forget about the other type error in the playground; in my code, I have proper slices instead of arrays.)
I understand this as saying "The slices might have different length, so you cannot do this".
However, how can I do this when I explicitly checked that the lengths are the same?

You should try split_at_mut(), something like this:
let len = prefix.len();
if slice.starts_with(prefix) {
let (left, _right) = slice.split_at_mut(len);
left.copy_from_slice(subst);
}
There is also explanation about this specific problem here: copy_from_slice()
Edit:
As Jmb stated in a comment, split_at_mut() is not needed:
let len = prefix.len();
if slice.starts_with(prefix) {
slice[..len].copy_from_slice(subst);
}

Related

Vectors borrowing and ownership [duplicate]

This question already has answers here:
What does it mean to pass in a vector into a `for` loop versus a reference to a vector?
(1 answer)
How can I solve "use of moved value" and "which does not implement the `Copy` trait"?
(1 answer)
What do I have to do to solve a "use of moved value" error?
(3 answers)
What does "cannot move out of index of" mean?
(2 answers)
Closed 2 years ago.
This doesn't work:
let vectors = vec![1, 2, 3, 4, 5, 6, 7];
for i in vectors {
println!("Element is {}", i);
}
let largest = vectors[0];
Error message:
error[E0382]: borrow of moved value: `vectors`
--> src/main.rs:8:19
|
2 | let vectors = vec![1, 2, 3, 4, 5, 6, 7];
| ------- move occurs because `vectors` has type `std::vec::Vec<i32>`, which does not implement the `Copy` trait
3 |
4 | for i in vectors {
| -------
| |
| value moved here
| help: consider borrowing to avoid moving into the for loop: `&vectors`
...
8 | let largest = vectors[0];
| ^^^^^^^ value borrowed here after move
The vector has been moved into the loop. Its ownership — and that of its individual elements — has been transferred there permanently.
But this works:
let largest = vectors[0];
let largest2 = vectors[0];
I don't know why; the vectors[0] value should have been moved to largest and largest2 should then fail, but it didn't.
When you use vectors inside a for..in loop, Rust will call the IntoIterator::into_iter trait method of the Vec, which takes ownership of self. Therefore you cannot use vectors afterwards.
use std::iter::IntoIterator;
// these are equivalent
for i in vectors { /* ... */ }
for i in IntoIterator::into_iter(vectors) { /* ... */ }
The index operator, on the other hands, calls the Index::index trait method of the Vec, which takes self by reference. Additionally, it automatically dereferences the value, so that if the items inside the vector implement Copy, they will be copied out of the vector instead of borrowed (you need to explicitly borrow if you want a reference):
use std::ops::Index;
// these are equivalent
let x = vectors[0];
let x = *Index::index(&vectors, 0);
// these are equivalent
let x = &vectors[0];
let x = Index::index(&vectors, 0);
The type of the values (probably i32) in your Vec implement the Copy trait, which means that they do not get moved out when indexing the vector, they get copied instead.
A Vec of such Copy types still doesn't implement Copy itself, so it gets moved into the loop. You can avoid this e.g. by writing
for i in vectors.iter() {
println!("Element is {}", *i);
}
The dereference (*) gives you an owned value like you'd get in your original code sample. It isn't necessary for println!, but might be necessary for other uses.

Why is it not possible to update a value in a HashMap using bracket [ ] notation? [duplicate]

This question already has answers here:
How can I update a value in a mutable HashMap?
(4 answers)
Closed 3 years ago.
I wrote a "count all character occurrences in a string" function with Rust, but updating/adding to the values does not work with bracket notation.
Why is that?
What works is this:
use std::collections::HashMap;
fn main() {
let myString = "Go ahead and count all my characters";
let mut myMap = HashMap::new();
for ch in myString.chars() {
*myMap.entry(ch).or_insert(0) += 1;
}
}
What does NOT work is:
for ch in myString.chars() {
myMap.entry(ch).or_insert(0);
*myMap[&ch] += 1;
}
In the latter case, the compiler complains:
error[E0614]: type `{integer}` cannot be dereferenced
--> src/main.rs:10:9
|
10 | *myMap[&ch] += 1;
| ^^^^^^^^^^^
This makes sense because they are copied and stored on the stack (if I understand correctly), but you also cannot add 1 to them if you do not try do dereference the value. It looks like the first version is the only option I have; is that correct? Why does it work there?
In Rust the operators can be overloaded by the standard operator traits. The index operator (or sometimes called as subscript operator) has two flavours: Index and IndexMut. If you are looking at the documentation of the HashMap it only implements the former, thus it cannot modify the returned referenced value.

How to populate a vector with predefined capacity? [duplicate]

This question already has answers here:
What's the difference between len() and capacity()?
(2 answers)
How to allocate space for a Vec<T> in Rust?
(3 answers)
How do I generate a vector of random numbers in a range?
(2 answers)
Closed 3 years ago.
I am trying to populate a vector after initialising it with with_capacity() as the number of elements is known prior to its creation and it seems more efficient with it.
The following code does NOT populate with random values AT ALL: println!("{}", v.len()); outputs zero.
use rand::Rng;
fn main() {
const NUMBER_OF_RANDOM_NUMBERS: usize = 10;
let mut v = Vec::with_capacity(NUMBER_OF_RANDOM_NUMBERS);
for i in &mut v {
*i += rand::thread_rng().gen_range(1, 2^32);
}
println!("{}", v.len());
}
My thinking is after let mut v = Vec::with_capacity(NUMBER_OF_RANDOM_NUMBERS) a brand new vector gets initialised with 10 zeros and then using rand::thread_rng().gen_range(1, 2^32) to insert, or should I say, add a random number to each zero.
Am I missing something here?
with_capacity does not initialize the values of the vector, it just allocates space for them. From the documentation:
It is important to note that although the returned vector has the
capacity specified, the vector will have a zero length. For an
explanation of the difference between length and capacity, see
Capacity and reallocation.
This means that when your loop code is executed, there are no items in the vector, and therefore it loops a total of zero times. Resulting in no change in the vector.

How to swap non-copyable elements in a vector? [duplicate]

This question already has an answer here:
How to swap the elements of an array, slice, or Vec?
(1 answer)
Closed 5 years ago.
I would like to swap String elements of a vector
let mut v_sa: Vec<String> = vec![];
...
let temp_a = v_sa_ib[j];
v_sa_ib[j] = v_sa_ib[j+1];
v_sa_ib[j+1] = temp_a;
It works with integers but not with Strings. I also tried to create a second vector temp_b (same type of temp_a) and to populate it instead of swapping but i got always the same error: the type of this value must be known in this context.
How can I fix it?
You can use the swap() method of Vec to swap two elements directly:
v_sa_ib(j, j+1);
There is also a generic swap function called std::mem::swap but it is difficult to use here because obtaining two mutable references two different elements of the same Vec is quite involved.
The reason why it worked with integers is that integers implement the Copy trait, so Rust can automatically create new copies.

The trait `std::marker::Sized` is not implemented for `[u16]` [duplicate]

This question already has answers here:
What is the return type of the indexing operation?
(2 answers)
How to get subslices?
(1 answer)
Closed 5 years ago.
I have a function that converts a wide string array as a [u16] to a String.
fn get_string_from_wide(wide_array: &[u16]) -> Result<String, String> {
let trimmed_wide = wide_array.iter()
.position(|char| *char == 0)
.map(|i| &wide_array[..i]) //<- remove `&` will give the error as the title
.unwrap_or(wide_array);
let os_str = OsString::from_wide(trimmed_wide);
os_str
.into_string()
.or(Err("Could not convert `Os_String` to `String`".to_string()))
}
Although the parameter is passed by reference, I still get the type as [u16] instead of &[u16]
If I remove the & the code compiles, but I don't want to pass a reference of a reference.
Is the var wide_array actually the data itself and not a reference as stated in the function parameter, and thus I still need to take a reference with & for referenced function calls? Or is it actually a reference to it?

Resources