Using "moved" values in a function - sorting

I want to learn Rust and am making a small program to deal with sound ques. I have a function with this signature:
fn edit_show(mut show: &mut Vec<Que>) {
show.sort_by(|a, b| que_ordering(&a.id, &b.id));
loop {
println!("Current ques");
for l in show {
println!("{}", que_to_line(&l));
}
}
}
I get an error:
use of moved value: 'show'
I cannot find anything on how to fix this. This seems like an odd error for sort since (I assume) if I was to do this in the main function where I pass in the value which seems quite useless.

Solution
Your problem is in this line:
for l in show {
...
}
This consumes the vector show. If you want to just borrow it's elements, you should write:
for l in &show {
...
}
If you want to borrow them mutably, write for l in &mut show.
Explanation
The Rust for loop expects a type that implements IntoIterator. First thing to note: IntoIterator is implemented for every Iterator. See:
impl<I> IntoIterator for I where I: Iterator
Now lets search for the Vec impls:
impl<T> IntoIterator for Vec<T> {
type Item = T
...
}
impl<'a, T> IntoIterator for &'a Vec<T> {
type Item = &'a T
...
}
impl<'a, T> IntoIterator for &'a mut Vec<T> {
type Item = &'a mut T
...
}
Here you can see that it's implemented for the Vec directly, but also for references to it. I hope these three impl blocks speak for themselves.

Related

generic callback with data

There is already a very popular question about this topic but I don;t fully understand the answer.
The goal is:
I need a list (read a Vec) of "function pointers" that modify data stored elsewhere in a program. The simplest example I can come up with are callbacks to be called when a key is pressed. So when any key is pressed, all functions passed to the object will be called in some order.
Reading the answer, it is not clear to me how I would be able to make such a list. It sounds like I would need to restrict the type of the callback to something known, else I don't know how you would be able to make an array of it.
It's also not clear to me how to store the data pointers/references.
Say I have
struct Processor<CB>
where
CB: FnMut(),
{
callback: CB,
}
Like the answer suggests, I can't make an array of processors, can I? since each Processor is technically a different type depending on the generic isntantiation.
Indeed, you can't make a vector of processors. Usually, closures all have different, innominable types. What you want instead are trait objects, which allow you to have dynamic dispatch of callback calls. Since those are not Sized, you'd probably want to put them in a Box. The final type is Vec<Box<dyn FnMut()>>.
fn add_callback(list: &mut Vec<Box<dyn FnMut()>>, cb: impl FnMut() + 'static) {
list.push(Box::new(cb))
}
fn run_callback(list: &mut [Box<dyn FnMut()>]) {
for cb in list {
cb()
}
}
see the playground
If you do like that, however, you might have some issues with the lifetimes (because your either force to move-in everything, or only modify values that life for 'static, which isn't very convenient. Instead, the following might be better
#[derive(Default)]
struct Producer<'a> {
list: Vec<Box<dyn FnMut() + 'a>>,
}
impl<'a> Producer<'a> {
fn add_callback(&mut self, cb: impl FnMut() + 'a) {
self.list.push(Box::new(cb))
}
fn run_callbacks(&mut self) {
for cb in &mut self.list {
cb()
}
}
}
fn callback_1() {
println!("Hello!");
}
fn main() {
let mut modified = 0;
let mut prod = Producer::default();
prod.add_callback(callback_1);
prod.add_callback(
|| {
modified += 1;
println!("World!");
}
);
prod.run_callbacks();
drop(prod);
println!("{}", modified);
}
see the playground
Just a few things to note:
You manually have to drop the producer, otherwise Rust will complain that it will be dropped at the end of the scope, but it contains (through the closure) an exclusive reference to modified, which is not ok since I try to read it.
Current, run_callbacks take a &mut self, because we only require for a FnMut. If you wanted it to be only a &self, you'd need to replace FnMut with Fn, which means the callbacks can still modify things outside of them, but not inside.
Yes, all closures are differents type, so if you want to have a vec of different closure you will need to make them trait objects. This can be archieve with Box<dyn Trait> (or any smart pointer). Box<dyn FnMut()> implements FnMut(), so you can have Processor<Box<dyn FnMut()>> and can make a vec of them, and call the callbacks on them: playground

Rust - create new Vec<Vec<K,V>>

I am trying to implement COLA(Cache oblivious look ahead array) in rust using this structure
struct COLA<K: Ord+Copy, V:Clone>{
levels: Vec<Vec<(K,V)>>,
}
My question is how to initialize levels in function fn new()?
I already tried initializing just the outer Vec but I that K,V should be inferred or something similar during creation.
You do only need to initialize the outer Vec, but to get the generic type arguments to follow it down to the method implementations, you need to stick them on the impl block:
impl<K: Ord + Copy, V: Clone> Cola<K, V> {
fn new() -> Self{
Cola::<K, V> {
levels: Vec::new(),
}
}
};

Rust: Mocking rand functions with gen_range

I am writing a small program that randomly selects an entry from an enum. Sample code:
#[derive(Debug)]
enum SettlementSize {
VILLAGE,
TOWN,
CITY
}
impl Distribution<SettlementSize> for Standard {
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> SettlementSize {
let res = rng.gen_range(0, 3);
match res {
0 => SettlementSize::VILLAGE,
1 => SettlementSize::TOWN,
2 => SettlementSize::CITY,
_ => panic!("Unknown value!")
}
}
}
fn get_settlement_size(mut rng: impl RngCore) -> SettlementSize {
let size: SettlementSize = rng.gen();
size
}
Now, of course I want to test it. That's why get_settlement_size takes the rng value.
#[test]
fn random_human_readable() {
let rng = StepRng::new(1, 1);
assert_eq!("Town", get_settlement_size(rng).human_readable());
}
Unfortunately, this doesn't work. When I added some printlns, the value returned from:
rng.gen_range(0, 3);
is always 0. I copied StepRng code into my test module to add println inside and I see next_u32 and next_u64 called. However, later the code disappears into UniformSampler and at that point it becomes too hard for me to follow. What am I doing wrong? Can I somehow retain the testability (which means being able to set fixed results for random in my mind)?
You're right,
it is easy to mock the primitive functions of the RngCore trait,
but the way they are used to avoid bias from low order bits and
bias from modulus calculations make it very tricky to mock the
more complicated functions in RngCore.
IMO the simplest way to approach this is to place a layer between your use of the Rng and the code you want to test.
So instead of this:
fn get_settlement_size(mut rng: impl RngCore) -> SettlementSize {
let size: SettlementSize = rng.gen();
size
}
you have
trait RngWrapper {
fn get_settlement_size(&mut self) -> SettlementSize;
}
fn get_settlement_size(rng: &mut impl RngWrapper) -> SettlementSize {
rng.get_settlement_size()
}
Now your "real" implementation looks like this
impl Distribution<SettlementSize> for Standard {
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> SettlementSize {
let res = rng.gen_range(0..3);
match res {
0 => SettlementSize::VILLAGE,
1 => SettlementSize::TOWN,
2 => SettlementSize::CITY,
_ => panic!("Unknown value!"),
}
}
}
struct Random<'a, R: RngCore> {
rng: &'a mut R,
}
impl<'a, R> RngWrapper for Random<'a, R>
where
R: RngCore,
{
fn get_settlement_size(&mut self) -> SettlementSize {
self.rng.gen()
}
}
And your mock could look something like this:
struct AlwaysTown {}
impl RngWrapper for AlwaysTown {
fn get_settlement_size(&mut self) -> SettlementSize {
SettlementSize::TOWN
}
}
Now you can test anything that uses get_settlement_size(), but you've not addressed testing of Random<'_, ThreadRng>::get_settlement_size - However this is now an isolated issue and doesn't require the "being able to set fixed results for random" that you mention in your question - instead I'd do a statistical test - that each of the expected cases comes out roughly the expected number of times.
If you want this rigorous, then you need a bit of stats (which I'm not going to put here) - but you should be able to put together a rough test that will pass 99.99+% of the time.
A full example, except the statistical tests on RngCore, is on the playground.

"Expected type parameter, found reference to type parameter" when implementing a generic cache struct

In the Closures chapter of the second edition of The Rust Programming Language, the writer implements a Cache struct and leaves it with a few problems for the reader to fix up, such as:
Accepting generic parameters and return values on the closure function
Allowing more than one value to be cached
I've attempted to fix those problems but I am quite stuck and can't make it work.
use std::collections::HashMap;
use std::hash::Hash;
struct Cacher<T, X, Y>
where
T: Fn(&X) -> &Y,
X: Eq + Hash,
{
calculation: T,
results: HashMap<X, Y>,
}
impl<T, X, Y> Cacher<T, X, Y>
where
T: Fn(&X) -> &Y,
X: Eq + Hash,
{
fn new(calculation: T) -> Cacher<T, X, Y> {
Cacher {
calculation,
results: HashMap::new(),
}
}
fn value<'a>(&'a mut self, arg: &'a X) -> &'a Y {
match self.results.get(arg) {
Some(v) => v,
None => {
let res = (self.calculation)(arg);
self.results.insert(*arg, res);
res
}
}
}
}
Where T is the closure function type, X is the argument type and Y is the return value type.
The error I get:
error[E0308]: mismatched types
--> src/main.rs:30:43
|
30 | self.results.insert(*arg, res);
| ^^^ expected type parameter, found &Y
|
= note: expected type `Y`
found type `&Y`
I understand this, but I can't think of an elegant solution for the whole ordeal.
You've stated that your closure returns a reference:
T: Fn(&X) -> &Y,
but then you are trying to store something that isn't a reference:
results: HashMap<X, Y>,
This is fundamentally incompatible; you need to unify the types.
In many cases, there's no reason to have a reference to a generic type because a generic type can already be a reference. Additionally, forcing the closure to return a reference means that a closure like |_| 42 would not be valid. Because of that, I'd say you should return and store the value type.
Next you need to apply similar logic to value, as it needs to take the argument by value in order to store it. Additionally, remove all the lifetimes from it as elision does the right thing: fn value(&mut self, arg: X) -> &Y.
Once you've straightened that out, apply the knowledge from How to lookup from and insert into a HashMap efficiently?:
fn value(&mut self, arg: X) -> &Y {
match self.results.entry(arg) {
Entry::Occupied(e) => e.into_mut(),
Entry::Vacant(e) => {
let res = (self.calculation)(e.key());
e.insert(res)
}
}
}
Round it off with some tests that assert it's only called once, and you are good to go. Note that we had to make decisions along the way, but they aren't the only ones we could have chosen. For example, we could have made it so that the cached value is cloned when returned.
use std::collections::HashMap;
use std::collections::hash_map::Entry;
use std::hash::Hash;
struct Cacher<F, I, O>
where
F: Fn(&I) -> O,
I: Eq + Hash,
{
calculation: F,
results: HashMap<I, O>,
}
impl<F, I, O> Cacher<F, I, O>
where
F: Fn(&I) -> O,
I: Eq + Hash,
{
fn new(calculation: F) -> Self {
Cacher {
calculation,
results: HashMap::new(),
}
}
fn value(&mut self, arg: I) -> &O {
match self.results.entry(arg) {
Entry::Occupied(e) => e.into_mut(),
Entry::Vacant(e) => {
let res = (self.calculation)(e.key());
e.insert(res)
}
}
}
}
#[test]
fn called_once() {
use std::sync::atomic::{AtomicUsize, Ordering};
let calls = AtomicUsize::new(0);
let mut c = Cacher::new(|&()| {
calls.fetch_add(1, Ordering::SeqCst);
()
});
c.value(());
c.value(());
c.value(());
assert_eq!(1, calls.load(Ordering::SeqCst));
}

Deriving std::hash::Hash for enums [duplicate]

I would like to use a HashSet as the key to a HashMap. Is this possible?
use std::collections::{HashMap, HashSet};
fn main() {
let hmap: HashMap<HashSet<usize>, String> = HashMap::new();
}
gives the following error:
error[E0277]: the trait bound `std::collections::HashSet<usize>: std::hash::Hash` is not satisfied
--> src/main.rs:4:49
|
4 | let hmap: HashMap<HashSet<usize>, String> = HashMap::new();
| ^^^^^^^^^^^^ the trait `std::hash::Hash` is not implemented for `std::collections::HashSet<usize>`
|
= note: required by `<std::collections::HashMap<K, V>>::new`
To make something the key of a HashMap, you need to satisfy 3 traits:
Hash — How do you calculate a hash value for the type?
PartialEq — How do you decide if two instances of a type are the same?
Eq — Can you guarantee that the equality is reflexive, symmetric, and transitive? This requires PartialEq.
This is based on the definition of HashMap:
impl<K: Hash + Eq, V> HashMap<K, V, RandomState> {
pub fn new() -> HashMap<K, V, RandomState> { /* ... */ }
}
Checking out the docs for HashSet, you can see what traits it implements (listed at the bottom of the page).
There isn't an implementation of Hash for HashSet, so it cannot be used as a key in a HashMap. That being said, if you have a rational way of computing the hash of a HashSet, then you could create a "newtype" around the HashSet and implement these three traits on it.
Here's an example for the "newtype":
use std::{
collections::{HashMap, HashSet},
hash::{Hash, Hasher},
};
struct Wrapper<T>(HashSet<T>);
impl<T> PartialEq for Wrapper<T>
where
T: Eq + Hash,
{
fn eq(&self, other: &Wrapper<T>) -> bool {
self.0 == other.0
}
}
impl<T> Eq for Wrapper<T> where T: Eq + Hash {}
impl<T> Hash for Wrapper<T> {
fn hash<H>(&self, _state: &mut H)
where
H: Hasher,
{
// do something smart here!!!
}
}
fn main() {
let hmap: HashMap<Wrapper<u32>, String> = HashMap::new();
}

Resources