Map boxed values to mutable dereferenced values in Rust - iterator

I have a iterator over a series of Boxed values. I would like to map this iterator to one over mutable references to the boxed values.
The following simplified example shows how this can be accomplished for immutable references. This example compiles fine.
let indices = [0usize, 1usize, 2usize];
let vec = vec![Box::new(1.0), Box::new(2.0), Box::new(3.0)];
let i = indices.iter().map(|index| vec[*index].deref()).map(|x| *x + 1.0);
However, for mutable references, like the example below, the compiler produces an error.
let indices = [0usize, 1usize, 2usize];
let mut vec = vec![Box::new(1.0), Box::new(2.0), Box::new(3.0)];
let i = indices.iter().map(|index| vec[*index].deref_mut()).map(|x| *x = *x + 1.0);
The compiler error is the following:
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter in function call due to conflicting requirements
--> src\port_graph/mod.rs:200:40
|
200 | let i = indices.iter().map(|index| vec[*index].deref_mut()).map(|x| *x = *x + 1.0);
| ^^^^^^^^^^^
|
note: first, the lifetime cannot outlive the lifetime as defined on the body at 200:39...
--> src\port_graph/mod.rs:200:40
|
200 | let i = indices.iter().map(|index| vec[*index].deref_mut()).map(|x| *x = *x + 1.0);
| ^^^^^^^^^^^^^^^^^^^^^^^
note: ...so that closure can access `vec`
--> src\port_graph/mod.rs:200:40
|
200 | let i = indices.iter().map(|index| vec[*index].deref_mut()).map(|x| *x = *x + 1.0);
| ^^^
note: but, the lifetime must be valid for the scope of call-site for function at 200:39...
--> src\port_graph/mod.rs:200:40
|
200 | let i = indices.iter().map(|index| vec[*index].deref_mut()).map(|x| *x = *x + 1.0);
| ^^^^^^^^^^^^^^^^^^^^^^^
note: ...so that return value is valid for the call
--> src\port_graph/mod.rs:200:32
|
200 | let i = indices.iter().map(|index| vec[*index].deref_mut()).map(|x| *x = *x + 1.0);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
How could this be fixed?
Edit: For a simple vector, one can simply do the following. However, the examples above are a simplicifation of a case where I want to iterate over a subset of nodes in a graph (petgraph crate), and I don't want to consume the graph itself.
let mut vec = vec![Box::new(1.0), Box::new(2.0), Box::new(3.0)];
let i = vec.iter_mut().map(|boxed| boxed.deref_mut()).map(|x| *x = *x + 1.0);

There is a tremendous difference between immutable and mutable references. The core principle of borrowing is:
Aliasing XOR Mutability
The Rust language guarantees that if you have a mutable reference, there is no other reference which aliases the same object.
In your case, instead of mapping again, let's collect... the addresses:
let c: Vec<_> = indices.iter().map(|index| vec[*index].deref())
.map(|x| x as *const _ as usize)
.collect();
println!("{:?}", c);
We get the list of addresses of elements in the vector.
The only reason those addresses differ is because the indices differ. If we are sneaky, and initialize indices to [0, 1, 2, 1], then we get aliasing.
If we can get aliasing based on a runtime property, then we should NOT also get mutability; and therefore the type system enforces this.
How is it enforced?
The vec is borrowed by the closure.
with deref, the closure borrows &Vec
with deref_mut, the closure borrows &mut Vec
You can witness the first one yourself:
let i = indices.iter().map(|index| vec[*index].deref())
.map(|x| x as *const _ as usize);
vec[0] = Box::new(3.0);
will fail with a note that the vector is already borrowed immutably by the closure.
The second one is a logical extension:
deref_mut takes a &mut self in argument,
which requires IndexMut which also takes a &mut self in argument,
therefore the closure requires mutable access to the vector.
So, each time you call the closure, it accesses a &mut Vec. Therefore, each time you call the closure NOTHING must alias this &mut Vec, and thus, no reference must leak outside the closure.
How is this achieved?
By tightening the lifetime of the reference that you get access to in the closure: each time you invoke the closure, you get a &'scope mut Vec reference where 'scope is the scope of the closure body and no more.
(This also relates to reborrowing and the fact that &mut T is not Copy: since you cannot be handed over a copy of the internally stored &mut T as it's not Copy, you are handed over a re-borrow &mut *vec which has a fresh lifetime).
What's the solution then?
Perform any and all computations directly in the closure where you have access to the Vec. In this closure, you have mutable access after all.
fn main() {
let indices = [0usize, 1usize, 2usize];
let mut vec = vec![Box::new(1.0), Box::new(2.0), Box::new(3.0)];
let c: Vec<_> =
indices.iter()
.map(|index| {
*vec[*index] = *vec[*index] + 1.0;
*vec[*index]
})
.collect();
println!("{:?}", c);
}
Correctly display [2, 3, 4].

Related

Is there any way to transform a variable (let) to constant (const)?

Does Rust have a method to transform a variable declared as let to a constant?
I would like to initialize an array with the size defined by the variable (tam), as I couldn't, I initialized with the size 90000. Is there any way to do this initialization with the variable (tam)?
//the variable tam receives an i32 that represents the size of the input and I would
//like to initialize an array with this size -> //let mut cities: [[i32; 2]; tam] = [[0; 2]; tam];
let args: Vec<String> = env::args().collect();
let filename = &args[1];
let tam: &i32 = &args[2].parse::<i32>().unwrap();
//let mut cities: [[i32; 2]; tam] = [[0; 2]; tam];
let mut cities: [[i32; 2]; 90000] = [[0; 2]; 90000];
No it is not possible to convert a variable to a const in Rust. Rust consts are more like a C #define than a variable, in that is in inlined, "copy-pasted", in all locations that uses it during compilation.
I would suggest making cities a Vec since that is something that you can dynamically size during runtime.

Implement a pairwise iterator

I have trouble writing code for a function that takes an iterator and returns an iterator that iterates in pairs (Option<T>, T) like so
a = [1,2,3]
assert pairwise(a) == `[(None, 1), (Some(1), 2), (Some(2), 3)]
fn pairwise<I, T>(&xs: &I) -> I
where
I: Iterator<Item = T>,
{
[None].iter().chain(xs.iter().map(Some)).zip(xs.iter())
}
fn main() {
let data: Vec<i32> = vec![1, 2, 3];
let newdata: Vec<Option<i32>, i32> = pairwise(&data).collect();
println!("{:?}", newdata);
}
error[E0599]: no method named `iter` found for type `I` in the current scope
--> src/main.rs:3:28
|
3 | [None].iter().chain(xs.iter().map(Some)).zip(xs.iter())
| ^^^^
|
Not sure why xs isn't iterable. I've stated it in the where clause haven't I?
fn pairwise<I, T>(&xs: &I) -> I
This doesn't make sense. See What is the correct way to return an Iterator (or any other trait)? and What is the difference between `e1` and `&e2` when used as the for-loop variable?.
I: Iterator<Item = T>,
There's no reason to specify that the Item is a T.
[None].iter()
It's better to use iter::once.
xs.iter()
There's no trait in the standard library that defines an iter method. Perhaps you meant IntoIterator?
let data: Vec<i32> = vec![1, 2, 3]
There's no reason to specify the type here; i32 is the default integral type.
Vec<Option<i32>, i32>
Vec<Option<i32>, i32>> // original version
This is not a valid type for Vec, and your original form doesn't even have balanced symbols.
After all that, you are faced with tough choices. Your example code passes in an iterator which has references to the slice but you've written your assertion such that you expect to get non-references back. You've also attempted to use an arbitrary iterator twice; there's no guarantee that such a thing is viable.
The most generic form I see is:
use std::iter;
fn pairwise<I>(right: I) -> impl Iterator<Item = (Option<I::Item>, I::Item)>
where
I: IntoIterator + Clone,
{
let left = iter::once(None).chain(right.clone().into_iter().map(Some));
left.zip(right)
}
fn main() {
let data = vec![1, 2, 3];
let newdata: Vec<_> = pairwise(&data).collect();
assert_eq!(newdata, [(None, &1), (Some(&1), &2), (Some(&2), &3)]);
let newdata: Vec<_> = pairwise(data.iter().copied()).collect();
assert_eq!(newdata, [(None, 1), (Some(1), 2), (Some(2), 3)]);
}
See also:
Iterating over a slice's values instead of references in Rust?
How to iterate over and filter an array?
How to create a non consuming iterator from a Vector
Why can I iterate over a slice twice, but not a vector?
The compiler suggests I add a 'static lifetime because the parameter type may not live long enough, but I don't think that's what I want
What is the correct way to return an Iterator (or any other trait)?
I know OP asked for "outer pairwise" ([(None, 1), (Some(1), 2), (Some(2), 3)]), but here is how I adapted it for "inner pairwise" ([(1, 2), (2, 3)]):
fn inner_pairwise<I>(right: I) -> impl Iterator<Item = (I::Item, I::Item)>
where
I: IntoIterator + Clone,
{
let left = right.clone().into_iter().skip(1);
left.zip(right)
}
For anyone here for "inner pairwise", you're looking for Itertools::tuple_windows.

How to extract values from &mut iterator?

I am trying to make an iterator that maps a string to an integer:
fn main() {
use std::collections::HashMap;
let mut word_map = HashMap::new();
word_map.insert("world!", 0u32);
let sentence: Vec<&str> = vec!["Hello", "world!"];
let int_sentence: Vec<u32> = sentence.into_iter()
.map(|x| word_map.entry(x).or_insert(word_map.len() as u32))
.collect();
}
(Rust playground)
This fails with
the trait core::iter::FromIterator<&mut u32> is not implemented for the type collections::vec::Vec<u32>
Adding a dereference operator around the word_map.entry().or_insert() expression does not work as it complains about borrowing which is surprising to me as I'm just trying to copy the value.
The borrow checker uses lexical lifetime rules, so you can't have conflicting borrows in a single expression. The solution is to extract getting the length into a separate let statement:
let int_sentence: Vec<u32> = sentence.into_iter()
.map(|x| *({let len = word_map.len() as u32;
word_map.entry(x).or_insert(len)}))
.collect();
Such issues will hopefully go away when Rust supports non-lexical lifetimes.

Chaining iterators of different types

I get type errors when chaining different types of Iterator.
let s = Some(10);
let v = (1..5).chain(s.iter())
.collect::<Vec<_>>();
Output:
<anon>:23:20: 23:35 error: type mismatch resolving `<core::option::Iter<'_, _> as core::iter::IntoIterator>::Item == _`:
expected &-ptr,
found integral variable [E0271]
<anon>:23 let v = (1..5).chain(s.iter())
^~~~~~~~~~~~~~~
<anon>:23:20: 23:35 help: see the detailed explanation for E0271
<anon>:24:14: 24:33 error: no method named `collect` found for type `core::iter::Chain<core::ops::Range<_>, core::option::Iter<'_, _>>` in the current scope
<anon>:24 .collect::<Vec<_>>();
^~~~~~~~~~~~~~~~~~~
<anon>:24:14: 24:33 note: the method `collect` exists but the following trait bounds were not satisfied: `core::iter::Chain<core::ops::Range<_>, core::option::Iter<'_, _>> : core::iter::Iterator`
error: aborting due to 2 previous errors
But it works fine when zipping:
let s = Some(10);
let v = (1..5).zip(s.iter())
.collect::<Vec<_>>();
Output:
[(1, 10)]
Why is Rust able to infer the correct types for zip but not for chain and how can I fix it? n.b. I want to be able to do this for any iterator, so I don't want a solution that just works for Range and Option.
First, note that the iterators yield different types. I've added an explicit u8 to the numbers to make the types more obvious:
fn main() {
let s = Some(10u8);
let r = (1..5u8);
let () = s.iter().next(); // Option<&u8>
let () = r.next(); // Option<u8>
}
When you chain two iterators, both iterators must yield the same type. This makes sense as the iterator cannot "switch" what type it outputs when it gets to the end of one and begins on the second:
fn chain<U>(self, other: U) -> Chain<Self, U::IntoIter>
where U: IntoIterator<Item=Self::Item>
// ^~~~~~~~~~~~~~~ This means the types must match
So why does zip work? Because it doesn't have that restriction:
fn zip<U>(self, other: U) -> Zip<Self, U::IntoIter>
where U: IntoIterator
// ^~~~ Nothing here!
This is because zip returns a tuple with one value from each iterator; a new type, distinct from either source iterator's type. One iterator could be an integral type and the other could return your own custom type for all zip cares.
Why is Rust able to infer the correct types for zip but not for chain
There is no type inference happening here; that's a different thing. This is just plain-old type mismatching.
and how can I fix it?
In this case, your inner iterator yields a reference to an integer, a Clone-able type, so you can use cloned to make a new iterator that clones each value and then both iterators would have the same type:
fn main() {
let s = Some(10);
let v: Vec<_> = (1..5).chain(s.iter().cloned()).collect();
}
If you are done with the option, you can also use a consuming iterator with into_iter:
fn main() {
let s = Some(10);
let v: Vec<_> = (1..5).chain(s.into_iter()).collect();
}

What's the difference between placing "mut" before a variable name and after the ":"?

Here are two function signatures I saw in the Rust documentation:
fn modify_foo(mut foo: Box<i32>) { *foo += 1; *foo }
fn modify_foo(foo: &mut i32) { *foo += 1; *foo }
Why the different placement of mut?
It seems that the first function could also be declared as
fn modify_foo(foo: mut Box<i32>) { /* ... */ }
If you're coming from C/C++, it might also be helpful to think of it basically like this:
// Rust C/C++
a: &T == const T* const a; // can't mutate either
mut a: &T == const T* a; // can't mutate what is pointed to
a: &mut T == T* const a; // can't mutate pointer
mut a: &mut T == T* a; // can mutate both
You'll notice that these are inverses of each other. C/C++ take a "blacklist" approach, where if you want something to be immutable you have to say so explicitly, while Rust takes a "whitelist" approach, where if you want something to be mutable you have to say so explicitly.
mut foo: T means you have a variable called foo that is a T. You are allowed to change what the variable refers to:
let mut val1 = 2;
val1 = 3; // OK
let val2 = 2;
val2 = 3; // error: re-assignment of immutable variable
This also lets you modify fields of a struct that you own:
struct Monster { health: u8 }
let mut orc = Monster { health: 93 };
orc.health -= 54;
let goblin = Monster { health: 28 };
goblin.health += 10; // error: cannot assign to immutable field
foo: &mut T means you have a variable that refers to (&) a value and you are allowed to change (mut) the referred value (including fields, if it is a struct):
let val1 = &mut 2;
*val1 = 3; // OK
let val2 = &2;
*val2 = 3; // error: cannot assign to immutable borrowed content
Note that &mut only makes sense with a reference - foo: mut T is not valid syntax. You can also combine the two qualifiers (let mut a: &mut T), when it makes sense.
The following natural language translation seems to clear things up for me...
let x = value;
x {binds immutably} to {immutable value}
let mut x = value;
x {binds mutably} to {possibly mutable value}
let x = &value;
x {binds immutably} to {a reference to} {immutable value}
let x = &mut value;
x {binds immutably} to {a reference to} {mutable value}
let mut x = &value;
x {binds mutably} to {a reference to} {immutable value}
let mut x = &mut value;
x {binds mutably} to {a reference to} {mutable value}
where
{binds mutably} means the binding can be reassigned
{mutable value} means the value's contents can change
To be able to mutate a value you need both a mutable binding and a mutable value
Note:
Reference mutability vs target mutability
A reference variable such as x, as in let x = &mut y, is a separate variable from the target variable y it is pointing to. In particular, x has its own location on the stack and mutability permissions. As such, if x is immutable, as it is here, then it cannot be reassigned to point to some other variable. That restriction is separate from the ability to mutate the target through it, as in *x = some_value; the target is a distinct variable with its own mutability permissions. However, if w is mutable, as in let mut w = &mut p, then it can indeed be reassigned to point to some other similarly typed variable: w = &mut z.
Mutable Variable of Reference Type
When you have
let mut x: &T = value;
This means that x is variable that refers to an instance of T, as if by storing the memory address of the T instance in x's value. This reference (i.e. the "memory address") is the subject of mutability in this context: x can be modified to refer to a different instance of T like this:
x = some_other_T_instance;
but the referant (i.e. the value of the T instance to which x refers) cannot be changed via x:
// Illegal
*x = a_different_value;
Immutable variable of Mutable Reference type
When you have
let x: &mut T = value;
This means that x is a variable that refers to a mutable instance of T. In this case, the referent (i.e. the actual value) is the subject of mutability. It can be modified through the reference like this
*x = some_other_value;
but the reference itself (i.e. the "memory address" in the variable x) cannot:
// illegal
x = a_different_value;