How to implement prepend for a linked list without needing to assign to a new variable? - data-structures

Something told me how to implement a linked list:
enum List {
Cons(u32, Box<List>),
Nil,
}
impl List {
fn prepend(self, elem: u32) -> List {
Cons(elem, Box::new(self))
}
}
When I want to use prepend, I need to do the following:
list = list.prepend(1);
However, I want to create a function that does not need to create a new variable every time prepend returns. I just want to change the list variable itself using prepend:
list.prepend(1);
Here is one implementation that I come up with, but it's not right:
fn my_prepend(&mut self, elem: u32) {
*self = Cons(elem, Box::new(*self));
}
The error is:
error[E0507]: cannot move out of borrowed content

List::prepend must move self because that is literally what is happening. The new head of the list is a new object and the old head is moved onto the heap, making the old variable invalid.
Inside my_prepend you have a mutable reference to self, but then you move its value so that the self reference becomes invalid. Even though it's only invalid temporarily, this is what the message "cannot move out of borrowed content" is complaining about.
One way to get around this is to move self out into a variable and simultaneously replace it with Nil, so that the self reference is never invalid. You can do that with mem::replace:
use std::mem;
fn my_prepend(&mut self, elem: u32) {
// Move the value of self into head, and leave self as Nil so it isn't invalid
let head = mem::replace(self, List::Nil);
// Reassign to self with the prepended value
*self = head.prepend(elem);
}

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

How to pop a value from cons list?

In the chapter 15.1 of The Book an example of Box<> usage for recursive type (cons list) implementation is shown. I tried to implement a method for this cons list to pop the outermost value out of the list, leaving the list with whatever left or Nil if nothing left. But it doesn't work, I can't figure out how to return the value while mutating the self after its deconstruction (and so borrowing?). Really none of the references in method make sense to me....
Is there no way to do this without creating a function that consumes the list and spits out both the value and new list?
Here is my code:
use crate::List::{Cons, Nil};
fn main() {
let mut list = Cons(1, Box::new(Cons(2, Box::new(Cons(3, Box::new(Nil))))));
println!("The first value is: {}.", list.pop().unwrap());
println!("The second value is: {}.", list.pop().unwrap());
}
#[derive(Debug)]
enum List {
Cons(i32, Box<List>),
Nil,
}
impl List {
// It seems to me I need to mutably borrow the list to change it
// but the way reference types behave later confuses me
fn pop(&mut self) -> Option<i32> {
if let Cons(value, list) = &self {
self = **list; // <- how to do this bit? self is borrowed...
Some(*value)
} else {
None
}
}
}
You can make your approach work by first moving the current list out of self, and replacing it with Nil. This way, you can match on the old list and still be able to assign to self:
fn pop(&mut self) -> Option<i32> {
let old_list = std::mem::replace(self, Nil);
match old_list {
Cons(value, tail) => {
*self = *tail;
Some(value)
}
Nil => None,
}
}
(Playground)

Want to know about automatic drop of data that no one references

I don't think the garbace collection of rust is fully explained with only the scope of the ownership.
I have googled it, and this is what I've got.
[ temporary data ]
If you reference temporary data, lifetime of the data differs by the expression where it comes : at the end of the scope, or at the end of the expression.
Look for the further explanation in here :
https://doc.bccnsoft.com/docs/rust-1.36.0-docs-html/reference/expressions.html#temporary-lifetimes
[ reassignment of variables ]
let a = String::from("first");
a = String::from("second");
In above case, first string data automatically drops while second assignment.
However, I couldn't search for more information since then.
In my prediction,
Fields of structures and indexes of arrays may be considered as "an independent variable" so that changing them to be considered as an reassignment of variable.
struct A {
a: String,
b: String
}
let mut x = A {
a: String::from("first"),
b: String::from("second")
}
x.a = String::from("reassignment"); // first string drops here
Also, we all know that if a variable drops, it drops all of its contents. (as below)
{
let a = vec!(String::from("first"), String::from("second"));
} // all the strings are dropped here.
OK. Then what about more complicated stuffs??
Box<T> or HashMap<String, i32> ... etc... which is data that consumes ownership of anyother data.
What if we change its inner data??
Is it the same act as reassigning a field of structure??
I wonder if they're just complex structures or totally different objects.
Is there any other rules of "auto drop of data" I should know?
If you want to known more and observe on automatic dropping then I recommend implementing Drop trait for a type. Rust doesn't have any garbage collector but the compiler does that job of adding instructions to cleanup the objects when they go out of scope.
Check this Rust RAII
If you implement Drop trait and use logging or printing in drop fn then you known when it goes out of scope and reclaimed. In below example observe when the drop method of Data struct gets called when the object goes out of scope.
use std::collections::HashMap;
#[derive(Debug)]
struct Data{
val: String
}
impl Drop for Data {
fn drop(&mut self) {
println!("Dropping for {:?}", self.val);
}
}
#[async_std::main]
async fn main() -> std::io::Result<()> {
{
let mut dataref = Data{val: "d0".to_string()};
{
let data = Data{val: "d1".to_string()};
let data2 = Data{val: "d2".to_string()};
dataref = data2;
println!("scope marker 1");
}
println!("scope marker 2");
let mut map = HashMap::new();
map.insert("k1".to_string(), Data{val:"v1".to_string()});
println!("Before chaning for k1");
map.insert("k1".to_string(), Data{val:"v1".to_string()});
println!("Changed k1");
}
Ok(())
}

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.

Rust: How to specify lifetimes in closure arguments?

I'm writing a parser generator as a project to learn rust, and I'm running into something I can't figure out with lifetimes and closures. Here's my simplified case (sorry it's as complex as it is, but I need to have the custom iterator in the real version and it seems to make a difference in the compiler's behavior):
Playpen link: http://is.gd/rRm2aa
struct MyIter<'stat, T:Iterator<&'stat str>>{
source: T
}
impl<'stat, T:Iterator<&'stat str>> Iterator<&'stat str> for MyIter<'stat, T>{
fn next(&mut self) -> Option<&'stat str>{
self.source.next()
}
}
struct Scanner<'stat,T:Iterator<&'stat str>>{
input: T
}
impl<'main> Scanner<'main, MyIter<'main,::std::str::Graphemes<'main>>>{
fn scan_literal(&'main mut self) -> Option<String>{
let mut token = String::from_str("");
fn get_chunk<'scan_literal,'main>(result:&'scan_literal mut String,
input: &'main mut MyIter<'main,::std::str::Graphemes<'main>>)
-> Option<&'scan_literal mut String>{
Some(input.take_while(|&chr| chr != "\"")
.fold(result, |&mut acc, chr|{
acc.push_str(chr);
&mut acc
}))
}
get_chunk(&mut token,&mut self.input);
println!("token is {}", token);
Some(token)
}
}
fn main(){
let mut scanner = Scanner{input:MyIter{source:"\"foo\"".graphemes(true)}};
scanner.scan_literal();
}
There are two problems I know of here. First, I have to shadow the 'main lifetime in the get_chunk function (I tried using the one in the impl, but the compiler complains that 'main is undefined inside get_chunk). I think it will still work out because the call to get_chunk later will match the 'main from the impl with the 'main from get_chunk, but I'm not sure that's right.
The second problem is that the &mut acc inside the closure needs to have a lifetime of 'scan_literal in order to work like I want it to (accumulating characters until the first " is encountered for this example). I can't add an explicit lifetime to &mut acc though, and the compiler says its lifetime is limited to the closure itself, and thus I can't return the reference to use in the next iteration of fold. I've gotten the function to compile and run in various other ways, but I don't understand what the problem is here.
My main question is: Is there any way to explicitly specify the lifetime of an argument to a closure? If not, is there a better way to accumulate the string using fold without doing multiple copies?
First, about lifetimes. Functions defined inside other functions are static, they are not connected with their outside code in any way. Consequently, their lifetime parameters are completely independent. You don't want to use 'main as a lifetime parameter for get_chunk() because it will shadow the outer 'main lifetime and give nothing but confusion.
Next, about closures. This expression:
|&mut acc, chr| ...
very likely does not what you really think it does. Closure/function arguments allow irrefutable patterns in them, and & have special meaning in patterns. Namely, it dereferences the value it is matched against, and assigns its identifier to this dereferenced value:
let x: int = 10i;
let p: &int = &x;
match p {
&y => println!("{}", y) // prints 10
}
You can think of & in a pattern as an opposite to & in an expression: in an expression it means "take a reference", in a pattern it means "remove the reference".
mut, however, does not belong to & in patterns; it belongs to the identifier and means that the variable with this identifier is mutable, i.e. you should write not
|&mut acc, chr| ...
but
|& mut acc, chr| ...
You may be interested in this RFC which is exactly about this quirk in the language syntax.
It looks like that you want to do a very strange thing, I'm not sure I understand where you're getting at. It is very likely that you are confusing different string kinds. First of all, you should read the official guide which explains ownership and borrowing and when to use them (you may also want to read the unfinished ownership guide; it will soon get into the main documentation tree), and then you should read strings guide.
Anyway, your problem can be solved in much simpler and generic way:
#[deriving(Clone)]
struct MyIter<'s, T: Iterator<&'s str>> {
source: T
}
impl<'s, T: Iterator<&'s str>> Iterator<&'s str> for MyIter<'s, T>{
fn next(&mut self) -> Option<&'s str>{ // '
self.source.next()
}
}
#[deriving(Clone)]
struct Scanner<'s, T: Iterator<&'s str>> {
input: T
}
impl<'m, T: Iterator<&'m str>> Scanner<'m, T> { // '
fn scan_literal(&mut self) -> Option<String>{
fn get_chunk<'a, T: Iterator<&'a str>>(input: T) -> Option<String> {
Some(
input.take_while(|&chr| chr != "\"")
.fold(String::new(), |mut acc, chr| {
acc.push_str(chr);
acc
})
)
}
let token = get_chunk(self.input.by_ref());
println!("token is {}", token);
token
}
}
fn main(){
let mut scanner = Scanner{
input: MyIter {
source: "\"foo\"".graphemes(true)
}
};
scanner.scan_literal();
}
You don't need to pass external references into the closure; you can generate a String directly in fold() operation. I also generified your code and made it more idiomatic.
Note that now impl for Scanner also works with arbitrary iterators returning &str. It is very likely that you want to write this instead of specializing Scanner to work only with MyIter with Graphemes inside it. by_ref() operation turns &mut I where I is an Iterator<T> into J, where J is an Iterator<T>. It allows further chaining of iterators even if you only have a mutable reference to the original iterator.
By the way, your code is also incomplete; it will only return Some("") because the take_while() will stop at the first quote and won't scan further. You should rewrite it to take initial quote into account.

Resources