How do I change an instance from a function? - rust

This is my code
struct AA{
size:i8
}
impl AA{
pub fn create()->Self{
Self { size: 10 }
}
pub fn world(mut self)->Self{
self.size+=2;
self
}
pub fn say(self){
println!("{}",self.size);
}
}
//cannot move out of `*aa` which is behind a mutable reference
fn hello(aa: &mut AA){//this function will make a change
aa.world();// <-- need to call world() from here
}
fn main() {
let mut a=AA::create();
hello(&mut a);
a.say();// <-- need to call say() from here after hello() does the change
//AA::create().world().say(); <-- this works
}
How can I achieve the following in rust?
From main(),
create instance
pass instance to world() so that it can change the instance
after the change occurs, call say() of the instance from main

Would this alternative work for you?
struct AA {
size: i8,
}
impl AA {
pub fn create() -> Self {
Self { size: 10 }
}
pub fn world(mut self) -> Self {
self.size += 2;
self
}
pub fn say(self) {
println!("{}", self.size);
}
}
fn hello(aa: AA) -> AA {
aa.world()
}
fn main() {
let mut a = AA::create();
a = hello(a);
a.say();
}
Notice that world returns a Self type and hello also returns AA. This way instead of passing a mutable reference to a in hello() we consume it and return a new version of it.
Another alternative would be for both world and say to accept references to self instead of consuming them, in which case the snippet would be:
pub fn world(&self) -> Self {
AA {
size: self.size + 2,
}
}
pub fn say(&self) {
println!("{}", self.size);
}

Related

Cannot return reference to temporary value with RwLock and iterators

I haven't found an answer to this in other questions.
I have reduced my problem to the following:
use std::sync::RwLock;
pub fn main() {
iter_lock().for_each(|v| {
println!("{}", v);
});
}
fn get_lock<'a>() -> &'a RwLock<Vec<u32>> {
static mut lock: RwLock<Vec<u32>> = RwLock::new(Vec::new());
unsafe { &lock }
}
fn iter_lock<'a>() -> impl std::iter::Iterator<Item = &'a u32> {
get_lock().read().unwrap().iter()
}
playground
The code above will not compile and give the following error:
error[E0515]: cannot return reference to temporary value
--> src/main.rs:15:5
|
15 | get_lock().read().unwrap().iter()
| --------------------------^^^^^^^
| |
| returns a reference to data owned by the current function
| temporary value created here
|
= help: use `.collect()` to allocate the iterator
Note that the static mut is not necessary in the code above, but I need it because I need to define a variable inside of an impl block.
I need to return an iterator, not a Vec because I am trying to avoid any allocations, and this function will always be used to iterate.
How can I solve this issue? I'm not afraid of using unsafe code, so unsafe suggestions are also welcome.
You can try something like this:
use std::sync::{RwLock, RwLockReadGuard};
pub fn main() {
let data = Data::new(&[1, 2, 3]);
data.iter().for_each(|x| println!("{:?}", x));
}
struct Data {
inner: RwLock<Vec<u32>>,
}
impl Data {
fn new(vec: &[u32]) -> Self {
Self {
inner: RwLock::new(vec.to_vec()),
}
}
fn iter(&self) -> Iter<'_> {
let d = self.inner.read().unwrap();
Iter::new(d)
}
}
struct Iter<'a> {
inner: RwLockReadGuard<'a, Vec<u32>>,
current_index: usize,
}
impl<'a> Iter<'a> {
pub fn new(inner: RwLockReadGuard<'a, Vec<u32>>) -> Iter<'a> {
Self {
inner,
current_index: 0,
}
}
}
impl Iterator for Iter<'_> {
type Item = u32;
fn next(&mut self) -> Option<Self::Item> {
if self.current_index >= self.inner.len() {
return None;
}
let item = &self.inner[self.current_index];
self.current_index += 1;
Some(*item)
}
}

Is it possible to pass a function receiving self as a parameter of a function of self?

Can I pass a function of an instance as a parameter to a function of the same instance, or do I have to pull the passed function out of the instance?
So, basically, does something like this work:
struct Some_Type {
}
impl Some_Type {
pub fn new() -> Self {
Some_Type{}
}
fn some_fn(&self, value: u32) -> u32 {
value
}
fn some_other_fn(&self, value: u32, input_fn: &dyn Fn(&Self, u32) -> u32) -> u32 {
input_fn(self, value)
}
}
fn main() {
let instance = Some_Type::new();
let fourty_two = instance.some_other_fn(42, &instance.some_fn);
}
Or do I have to write it like this:
struct Some_Type {
}
impl Some_Type {
pub fn new() -> Self {
Some_Type{}
}
fn some_other_fn(&self, value: u32, fn: &dyn Fn(&Self, u32) -> u32) -> u32 {
fn(value)
}
}
fn some_fn(&Some_Type, value: u32) -> u32 {
value
}
fn main() {
let instance = Some_Type::new();
let fourty_two = instance.some_other_fn(42, &some_fn);
}
I found a solution myself. One can write
fn main() {
let instance = Some_Type::new();
let fourty_two = instance.some_other_fn(42, &Some_Type::some_fn);
}
and pass &self to fn inside Some_Type.some_other_fn in the first example.

Closure lifetime in Rust through simple pattern

I'm trying to recreate a simple callback pattern in Rust using 2 structs. One will pass a bit of logic to execute whenever the other one is ready. The issue here is that the logic will run only if a certain value from the struct is true.
I can understand why the reference to Foo needs to live for 'static in this case, but I'm not sure how to refactor so that it compiles.
Seems like a pretty regular use case, but maybe I'm missing something since I'm new to Rust.
struct Foo {
value: bool,
}
struct Bar {
closure: Box<dyn Fn() -> ()>,
}
impl Foo {
fn new() -> Self {
Foo {
value: false,
}
}
fn set_closure(&self, b: &mut Bar) {
b.closure = self.get_closure();
}
fn get_closure(&self) -> Box<dyn Fn() -> ()> {
return Box::new(|| {
if self.value {
println!("true");
} else {
println!("false");
}
});
}
}
impl Bar {
fn new() -> Self {
Bar {
closure: Box::new(|| {})
}
}
}
fn main() {
let foo = Foo::new();
let mut bar = Bar::new();
foo.set_closure(&mut bar);
let closure = bar.closure;
closure();
}
Playground link -> here
You need to move the value into the closure:
fn get_closure(&self) -> Box<dyn Fn() -> ()> {
let value = self.value;
Box::new(move || {
if value {
println!("true");
} else {
println!("false");
}
})
}
Notice that in your example value is a bool which is Copy. If not you can either capture a reference or clone it. (If capturing a reference you may need to adjust some lifetimes there).
Playground

Sending a closure (which returns a struct with a trait) to a thread leads to sized error

I'm trying to send a closure which will generate a structure to a thread, however when I try to do it I get a Sized error. I understand the error (the size is indeed not known at compile time), however adding Boxes and other such tricks does not seem to solve it.
I've tried to look into how to implement the Sized trait, however it seems to be quite special and honestly above my understanding.
I've written a minimal reproducible example:
use std::thread;
trait DataProcess {
fn start(&self);
fn run(&self);
fn stop(&self);
}
struct SomeDP {
name: String,
}
impl DataProcess for SomeDP {
fn start(&self) {
println!("Started");
}
fn run(&self) {
println!("Running");
}
fn stop(&self) {
println!("Stopped");
}
}
fn thread_maker(builder: Box<dyn Fn() -> (dyn DataProcess + Send)>) {
let thread_builder = thread::Builder::new();
let handle = thread_builder.spawn(move || {
let dp = builder();
dp.start();
});
}
fn main() {
let dp_builder = || SomeDP {
name: "nice".to_string(),
};
thread_maker(Box::new(dp_builder));
}
Which you can also find on the playground here
This works
use std::thread;
trait DataProcess{
fn start(&self);
fn run(&self);
fn stop(&self);
}
struct SomeDP{
name: String
}
impl DataProcess for SomeDP{
fn start(&self){println!("Started");}
fn run(&self){println!("Running");}
fn stop(&self){println!("Stopped");}
}
fn thread_maker<F>(builder: F)
where
F: Fn() -> Box<dyn DataProcess>,
F: Send + 'static {
let thread_builder = thread::Builder::new();
let handle = thread_builder.spawn(
move ||{
let dp = builder();
dp.start();
}
);
}
fn main(){
let dp_builder = || -> Box<dyn DataProcess> {
Box::new(SomeDP{name: "nice".to_string()})
};
thread_maker(dp_builder);
}

How to make &mut self from &self?

I want to expose a public function with immutable self which calls a private function with mutable self.
struct Foo {
value: i32,
}
impl Foo {
fn f1(&self) {
self.f2(); // <--- is it possible to make self mutable?
}
fn f2(&mut self) {
self.value = 5;
}
}
fn main() {
let foo = Foo { value: 0 };
foo.f1();
}
When compiling this code I get an error
cannot borrow immutable borrowed content *self as mutable
Is it possible to make self mutable?
EDIT:
After missing that last sentence.. you could get away with wrapping the property in a Cell:
use std::cell::Cell;
struct Foo { value: Cell<i32> }
impl Foo {
fn f1(&self) {
self.f2();
}
fn f2(&self) {
self.value.set(5);
}
}
fn main() {
let foo = Foo { value: Cell::new(0) };
foo.f1();
println!("{:?}", foo.value.get()); // prints 5
}
What you want cannot be done: you cannot convert a non-mutable reference into a mutable one.
But you can get almost that with RefCell:
struct Foo { value: RefCell<i32> }
impl Foo {
fn f1(&self) {
let mutValue = self.value.borrow_mut();
*mutValue = 5;
}
}
I didn't even need the f2 function!

Resources