Borrow a value wrapped in an Option using a method [duplicate] - rust

This question already has answers here:
Cannot move out of value which is behind a shared reference when unwrapping
(2 answers)
How to borrow an unwrapped Option<T>? [duplicate]
(1 answer)
Closed 3 years ago.
I would like to write a method on a struct which borrows a value wrapped in an Option in one of its properties/fields.
Is it doable ?
Consider
struct A {}
struct Obj {
a: Option<A>
}
impl Obj {
fn ref_to_a(&self) -> &A {
//&self.a.unwrap() <-- How do I implement this ?
}
}
Playground

You can use Option::as_ref to "Convert from Option<T> to Option<&T>."
impl Obj {
fn ref_to_a(&self) -> &A {
self.a.as_ref().unwrap()
}
}
Of course you shouldn't use unwrap, but at least expect.

I don't know why you are not borrowing Option itself, but you can mimic unwrap behavior by this way :
impl Obj {
fn ref_to_a(&self) -> &A {
match self.a {
Some(ref a) => return a,
None => panic!("There is no value"),
}
}
}
Note :
Should I avoid unwrap in production application?

Related

How to return a reference to a value owned by a Vec within a Rc<RefCell<_>>? [duplicate]

This question already has answers here:
Obtain a reference from a RefCell<Option<Rc<T>>> in Rust
(1 answer)
How do I borrow a RefCell<HashMap>, find a key, and return a reference to the result? [duplicate]
(1 answer)
How do I return a reference to something inside a RefCell without breaking encapsulation?
(3 answers)
Closed 12 months ago.
Assume following code
pub struct Universe {
components: Rc<RefCell<Vec<Component>>>,
active_component: Rc<RefCell<Option<usize>>>,
}
I would like to introduce a convenience method that returns a mutable reference to the active component, e.g.
fn get_active_component(&mut self) -> Option<&mut Component> {
if let Some(active_component_idx) = self.active_component.borrow().as_ref() {
let i = *active_component_idx;
return self.components.borrow_mut().get_mut(i);
}
Option::None
}
which results in error
145 | return self.components.borrow_mut().get_mut(i);
| ----------------------------^^^^^^^^^^^
| |
| returns a reference to data owned by the current function
| temporary value created here
I do understand the error. The borrow_mut() creates a temporary variable which goes out of scope after the function returns. But I have absolutely no idea how you would realize such a method in rust apart from always inlining the code.
The standard way would be to mimic what RefCell does -- return a proxy struct wrapping the RefMut from .borrow_mut() and containing the vector index, implementing Deref and DerefMut.
pub struct ComponentHandle<'a> {
vecref: RefMut<'a, Vec<Component>>,
index: usize,
}
impl Deref for ComponentHandle<'_> {
type Target = Component;
fn deref(&self) -> &Component {
// SAFETY: We already verified the index is valid, RefCell won't
// dispense another mutable reference while we hold the RefMut, and we
// don't modify the vector's length, so we know this index is valid.
unsafe { self.vecref.get_unchecked(self.index) }
}
}
impl DerefMut for ComponentHandle<'_> {
fn deref_mut(&mut self) -> &mut Component {
// SAFETY: We already verified the index is valid, RefCell won't
// dispense another mutable reference while we hold the RefMut, and we
// don't modify the vector's length, so we know this index is valid.
unsafe { self.vecref.get_unchecked_mut(self.index) }
}
}
impl Universe {
fn get_active_component(&mut self) -> Option<ComponentHandle<'_>> {
if let Some(active_component_idx) = self.active_component.borrow().as_ref() {
let vecref = self.components.borrow_mut();
let index = *active_component_idx;
if index < vecref.len() {
return Some(ComponentHandle { vecref, index });
}
}
None
}
}
Alternatively, this function could accept a closure to invoke, passing it the bare reference. This is simpler to code, though less idiomatic:
fn get_active_component<F>(&mut self, f: F)
where F: FnOnce(Option<&mut Component>)
{
if let Some(active_component_idx) = self.active_component.borrow().as_ref() {
let i = *active_component_idx;
f(self.components.borrow_mut().get_mut(i));
} else {
f(None);
}
}

Change value in found item [duplicate]

This question already has answers here:
What is the difference between iter and into_iter?
(5 answers)
Closed last month.
I'm trying to find and change a specific item in an iterator like this:
struct ItemType {
name: &'static str,
value: i32
}
struct OuterType {
list: Vec<ItemType>
}
impl OuterType {
pub fn setByName(
self: &mut Self,
name: &str
) -> Result<(), String> {
match self.list.iter().find(|item| item.name == name) {
Some(item_found) => {
item_found.value = 1;
},
None => {
return Err(format!("unrecognized item name (was \"{}\")", name));
}
}
Ok(())
}
}
But this does not compile because of several reasons, some of which:
no Copy trait (don't want to change a copy, I want to change the item in-place);
not borrowed, add & (does not help);
not mutable, add mut (does not help);
cannot assign to item_found.value which is behind a &;
at some point it says & can PROBABLY be removed... (WHAT?);
those errors are cyclic, I'm ping-pong-ing between them with no exit.
I've also tried to .find(|&item| ...).
What is going on? Don't I get to own the value returned by find()? And how am I supposed to change item_found.value? It's just an integer in a struct which is one of several in a vector I get the iterator for.
Just use iter_mut instead of iter when you need to mutate the value:
match self.list.iter_mut().find(...) {...}
Playground

How can I return a reference to the inner data of a RefCell<Option<T>>>? [duplicate]

This question already has answers here:
How do I return a reference to something inside a RefCell without breaking encapsulation?
(3 answers)
Closed 2 years ago.
I'm creating a lazily loading struct:
pub struct LazyData<T, U:FnOnce() -> T> {
data: RefCell<Option<T>>,
generator: RefCell<Option<U>>,
}
impl<T,U:FnOnce() -> T> LazyData<T,U> {
pub fn new(generator:U) -> LazyData<T,U> {
LazyData {
data: RefCell::new(None),
generator: RefCell::new(Some(generator)),
}
}
...
}
I've tried to implement a get method that will return the lazily loaded data:
pub fn init(&self) {
if self.data.borrow().is_none() {
let generator = self.generator.replace(None).unwrap();
let _none = self.data.replace(Some(generator()));
};
}
pub fn get(&self) -> &T {
self.init();
self.data.borrow().as_ref().unwrap()
}
But the compiler complains that I'm returning a value referencing data owned by the current function. This error makes sense to me, but I'm not sure how to work around it.
Here's a link to a full example.
Found a workaround here! I can use Ref::map to get to the inner data:
pub fn get(&self) -> Ref<T> {
self.init();
Ref::map(self.data.borrow(), |borrow| {
borrow.as_ref().unwrap()
})
}
This method now returns Ref instead of &T, but I think that should be fine.

How do I pass a method as a callback/handler parameter to a function? [duplicate]

This question already has an answer here:
How to pass a method as callback
(1 answer)
Closed 2 years ago.
The following executor function takes a function and calls it with a parameter:
fn executor(func: &dyn Fn(String)) {
// Invoke the callback
func(String::from("Hello"));
}
This code doesn't compile:
struct MyStruct {
the_answer: u32,
}
impl MyStruct {
pub fn run(&self) {
executor(&self.printer_method); // <--- Does not compile - rustc(E0615)
executor(&MyStruct::printer_associated_func); // <--- ...but this does.
}
fn printer_method(&self, msg: String) {
// Access to self.the_answer
println!(
"The answer is {}, your message is: {}",
self.the_answer, msg
);
}
fn printer_associated_func(msg: String) {
// No access to self.the_answer
println!("printer: {}", msg);
}
}
fn main() {
let my_struct = MyStruct { the_answer: 42 };
my_struct.run();
}
The full error message:
error[E0615]: attempted to take value of method `printer_method` on type `&MyStruct`
--> src/main.rs:12:24
|
12 | executor(&self.printer_method);
| ^^^^^^^^^^^^^^ help: use parentheses to call the method: `printer_method(...)`
How do I pass a method (i.e. not an associated function or just a context-less function) to the executor() function?
If I'm hitting the language's limits here, which alternatives would I have to access the member variable self.the_answer from within a callback?
You cannot obtain a callable pointer to a member function with the syntax you wrote because to be able to call it you need a self, so your callable needs to capture self, but function pointers always have an empty capture set. That is, if you get a pointer to MyStruct::printer_method your function actually accepts two arguments, not one.
To do what you want, you can use a closure that captures your self:
executor(&|msg| self.printer_method(msg));
Note that you actually need a pointer to the closure, because you are passing a dyn Fn instead of an impl Fn.

Vec of Rng in struct field, cannot borrow immutable field as mutable [duplicate]

This question already has answers here:
How I can mutate a struct's field from a method?
(2 answers)
Cannot modify a struct field from implementation: "cannot borrow immutable borrowed content as mutable"
(1 answer)
Closed 7 years ago.
I wanted to create a structwith a field containing a Vec<ThreadRng>.
So this works fine, I have a list of generators stored in Foo.generators:
extern crate rand;
use std::vec::Vec;
use rand::{Rng, ThreadRng};
struct Foo {
generators: Vec<ThreadRng>,
}
impl Foo {
fn new() -> Foo {
Foo { generators: vec![rand::thread_rng(), rand::thread_rng()]}
}
}
Now I would like to use it, say in a bar method:
impl Foo {
fn bar(&self) -> i32 {
self.generators[0].gen::<i32>()
}
}
But that I can't, and I get a cannot borrow immutable field 'self.generators' as mutable.
As I understand I cannot use the gen method of ThreadRng because it requires a mutable reference to the RNG (gen<T: Rand>(&mut self)) and since the definition of my field Foo.generators "Vec<ThreadRng>" doesn't specify that the ThreadRng should be mutable, I can't do anything with it that requires mutability.
First question: is my understanding of what's happening correct, or am I completely wrong? If so, could someone explain to me what's really happening?
Second question: admitting that my understanding is correct, how am I supposed to allow actions that requires mutability on my ThreadRngs?
Thanks in advance!
You need to borrow self mutably:
impl Foo {
fn bar(&mut self) -> i32 {
self.generators[0].gen::<i32>()
}
}

Resources