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

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(),
}
}
};

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

Is there a way to use postfix notation to call a function in Rust without defining a new trait?

Perhaps my terminology is wrong, but is there a way to use postfix notation to call a function in Rust without defining a new trait? Basically, I have a vector of &str and I'd like to convert them into a string with the notation myvec.as_string(). Currently, I can do this with the code
trait Foo {
fn as_string(&self) -> String;
}
impl Foo for Vec<&str> {
fn as_string(&self) -> String {
let mut mystr = self
.iter()
.fold(String::new(),|sum,s| format!("{}{}:", sum, s));
mystr.pop();
mystr
}
}
fn main() {
let my_vec = vec!["bar", "buz", "baz"];
use crate::Foo;
println!("{}", my_vec.as_string());
}
That said, in order to make this work, I needed to define a trait called Foo that I don't really care about and the trait needed to be opened with use crate::Foo prior to the call to as_string. Is there a better way to accomplish this? And, to be clear, I'd like to avoid the notation as_string(myvec) if possible because the postfix notation has been nice for chaining together commands.
This is a common pattern!
If you want to add methods to a type that is defined in another crate, the official way to do so is it define a trait and implement it for that type. If the type is from another crate then this is the only way to do it.
A ubiquitous example of this is the crate itertools which uses a trait to add useful methods to every existing implementation of std::iter::Iterator.
Itertools works just as you describe. There is a trait which declares a number of methods:
pub trait Itertools : Iterator {
fn interleave<J>(self, other: J) -> Interleave<Self, J::IntoIter>
where J: IntoIterator<Item = Self::Item>,
Self: Sized
{
interleave(self, other)
}
// etc...
}
It is defined for all Iterators:
impl<T: ?Sized> Itertools for T where T: Iterator { }
And, whenever you want to use these extra methods, you import it:
use itertools::Itertools;
let it = (1..7).interleave(vec![-1, -2]);
itertools::assert_equal(it, vec![1, -1, 2, -2, 3, 4, 5, 6]);
Use a macro such as the following provided by Lucretiel...
macro_rules! express {
($thing:ident $( . $method:ident ( $($args:tt)* ) )*) => {{
let mut thing = $thing;
$( thing.$method($($args)*); )*
thing
}};
}
Example usage...
fn main() {
let a = vec![];
let b = express!(a.push(1).push(2).push(34));
println!("{:?}", b);
}
Gist

How to store method pointers in a HashMap and call them

I am trying to write a chip8 emulator and the borrow checker is giving me a hard time.
The idea is to decode an opcode through looking up a method pointer inside a HashMap and then executing this method pointer but I cannot get the mutable method pointers to work correctly:
struct Chip8 {
opcode: u16,
//... other fields
jump_table: HashMap<u16, Box<fn(&mut Chip8)>>,
}
Function using the pointers:
fn execute_decoded(&mut self, key: u16) {
let func = self.jump_table.get(&key);
match func {
Some(func) => func(self),
None => {
println!("invalid op: {}", self.opcode);
sleep(Duration::from_millis(10000));
return;
}
}();
self.program_counter = self.program_counter + 2;
}
The checker complains:
cannot borrow `*self` as mutable because `self.jump_table` is also borrowed as immutable
--> main.rs:168:36
|
165 | let func = self.jump_table.get(&key);
| --------------- immutable borrow occurs here
...
168 | Some(func) => func(self),
| ^^^^ mutable borrow occurs here
...
178 | }
| - immutable borrow ends here
I do not understand why this error is happening.
Why is self.jump_table.get(&key) borrowing at all? Based on the signature of execute_decoded, I was assuming that it works on a mutable borrowed version of self and no additional borrowing is needed.
There's no reason to Box the function pointers in the HashMap, that only introduces unneeded indirection.
As has already been mentioned, you are borrowing the function pointer. The thing is, there's no reason to. You can just copy the function pointer to disassociate it from the HashMap:
use std::collections::HashMap;
struct Chip8 {
jump_table: HashMap<u16, fn(&mut Chip8)>,
}
impl Chip8 {
fn execute_decoded(&mut self, key: u16) {
let func = self.jump_table.get(&key).map(|x| *x);
match func {
Some(func) => func(self),
None => {
println!("invalid op");
}
};
}
}
fn main() {}
A HashMap in Rust owns everything inside of it. In order to get your function pointer you are borrowing it with let func = self.jump_table.get(&key);. So now, func is immutably borrowing self.jump_table (which is an element of self).
The issue is that you are then trying to pass all of self into func. This would be fine if you were passing in self immutably, as you can borrow self immutably as many times as you want. However, since you are trying to mutably borrow self the compiler will not allow you to do so since you have just immutably borrowed a portion of self (specifically self.jump_table).
One way to fix this is to split up your Chip8 struct into smaller structs, such that you can pass all of the necessary information into func without also passing in jump_table.

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();
}

Using "moved" values in a function

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.

Resources