This question already has an answer here:
Why does removing return give me an error: expected type `()` but found type
(1 answer)
Closed 6 years ago.
I have a world object:
use rand::{thread_rng, Rng};
use super::world::World;
pub struct Worlds {
worlds: Vec<World>
}
impl Worlds {
pub fn new(world: Vec<World>) -> Worlds {
Worlds { worlds: world }
}
pub fn get_random_world(&self) -> World {
let mut rng = thread_rng();
if self.worlds.len() > 0 {
let world_index: usize = rng.gen_range(0, self.worlds.len());
self.worlds[world_index]
}
self.worlds[0]
}
}
The structure Worlds takes a vector of structures called World (I can post that code if you need it).
get_random_world is supposed to return a World structure, and does with self.worlds[world_index], but apparently it expects a ().
I'm lost; I told it what to return, it returns that but it expects something different?
|
20 | self.worlds[world_index]
| ^^^^^^^^^^^^^^^^^^^^^^^^ expected (), found struct `game::world::world::World`
|
= note: expected type `()`
= note: found type `game::world::world::World`
I'm not sure what to do at this point.
Your if block doesn't return anything.. flow will fall through here:
if self.worlds.len() > 0 {
let world_index: usize = rng.gen_range(0, self.worlds.len());
self.worlds[world_index]
} // <--- ... this drops down
self.worlds[0]
Here is a simple reproduction of your issue: Playground link
There are two ways you can fix this. First, you can explicitly return in the conditional (View it on the playground):
if self.worlds.len() > 0 {
let world_index: usize = rng.gen_range(0, self.worlds.len());
return self.worlds[world_index]; // Explicitly return out of here
}
self.worlds[0]
The more "idiomatic" approach I guess would be to add an else block, so that the value the conditional evaluates to is actually what the function returns (View it on the playground):
if self.worlds.len() > 0 {
let world_index: usize = rng.gen_range(0, self.worlds.len());
self.worlds[world_index]
} else {
self.worlds[0]
}
Now, no matter what logical branch the code takes, the expression that results will be returned from the function.
Related
I'm working thru some programming exercises on Exercism when I ran into this problem. It's not clear to me why the type of the closure set to for_each() even matters.Here's the entire Rust program:
use std::collections::HashSet;
// reformat(word) returns a tuple mapping its argument to (lowercase, sorted_lowercase)
fn reformat(word: &str) -> (String,String) {
let lower = word.to_lowercase();
let mut char_vec : Vec<char> = lower.chars().collect();
char_vec.sort_unstable();
let sorted : String = char_vec.iter().collect();
(lower,sorted)
}
// Items in 'possible_anagrams' will be added to the set if they contain all of the
// same characters as 'word' but arranged in a different order.
fn anagrams_for<'a>(word: &str, possible_anagrams: &'a [&str]) -> HashSet<&'a str> {
let mut set = HashSet::<&str>::new();
let w = reformat(word);
let is_anagram = |x:&str|->bool{let t=reformat(x);w.1==t.1&&w.0!=t.0};
possible_anagrams.iter().filter(|x|is_anagram(x)).for_each(|x| set.insert(x));
set
}
fn main() {
let a : [&str; 4] = ["FRBA", "Braf", "wut", "batt"];
println!("{:#?}", anagrams_for("Frab", &a));
}
I get an error message about the argument to the for_each() here:
|
18 | possible_anagrams.iter().filter(|x|is_anagram(x)).for_each(|x| set.insert(x));
| ^^^^^^^^^^^^^
expected `()`, found `bool`
The error message is not at all clear to me. I've tried various remedies but any change I make seems to make matters worse, i.e., more error messages.
I have a completely different manifestation of the anagrams_for() function that does work properly. So as far as the coding exercise goes, I have solved it via the following version of this function:
pub fn anagrams_for<'a>(word: &str, possible_anagrams: &'a[&str]) -> HashSet<&'a str> {
let mut set = HashSet::<&str>::new();
let w = reformat(word);
for x in possible_anagrams {
let test = reformat(x);
if w.1 == test.1 && w.0 != test.0 {
set.insert(x);
}
}
set
}
This one functions as I want. I've included it here as an example of what I want the so-far-not-working code to do.
HashSet::insert() returns bool (true if the value was already in the set).
Iterator::for_each() expects its closure to return the unit type (), or "nothing" (void in C).
Rust is expression-oriented: (almost) everything is an expression. Closures (and functions) returns the value of their last expression. That is, || expr is the same as || { return expr; }, and thus your closure returns the return value of insert() - a bool, while for_each() expects it to return ().
The fix is simple: you just need to discard insert()'s return value. It is done by making it into a statement, by appending a semicolon to it. This will also require you to use a block:
possible_anagrams.iter().filter(|x| is_anagram(x)).for_each(|x| { set.insert(x); });
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);
}
}
This question already has answers here:
How can I conditionally provide a default reference without performing unnecessary computation when it isn't used?
(2 answers)
Closed 2 years ago.
I have a function which takes a reference and a condition. If the condition is false, it uses the passed in reference, but when the condition is true, it use a temp reference pointing to the local variable in the function.
The Foo struct is NOT Copy or Clone.
The commented-off code won't compile and I have an ugly way to work around this problem:
#[derive(Debug)]
struct Foo {
a: String,
}
fn f(r: &Foo, cond: bool) {
// let a = if cond { &Foo { a: "456".into() } } else { r };
// use a temp variable `t` can solve this problem in this demo code,
// but what if in production code where build tmp var `t` is expensive?
let mut a = r;
let t = &Foo { a: "456".into() };
if cond {
a = &t;
}
// use the ref here, inside the function.
println!("{:#?}", a);
}
fn main() {
let a = Foo { a: "123".into() };
f(&a, true);
}
Because the use of the reference is limited in the function, is there a way to tell the compiler: do not free the temp var created in the if branch, keep it until the function return and destroy it when destroy the stack frame?
I think there should be a way without using heap memory. On the other hand, when using Box, the type produced in the two if branch will be different, one is &Foo and another is Box<Foo>, so this won't be the right way.
Cow to the rescue! Cow is an enum that represents either (1) a thing that we own or (2) a thing we have borrowed.
#[derive(Debug, Clone)]
struct Foo {
a: String,
}
fn f(r: &Foo, cond: bool) {
use std::borrow::Cow;
let a: Cow<Foo> = if cond {
// (1) a thing that we own, or
Cow::Owned(Foo { a: "456".into() })
} else {
// (2) a thing we have borrowed
Cow::Borrowed(r)
};
// use the ref here, inside the function.
println!("{:#?}", a);
// if a is a Cow::Owned, the owned thing is dropped properly
// if a is a Cow::Borrowed, the reference is dropped.
}
fn main() {
let a = Foo { a: "123".into() };
f(&a, true);
}
Cow requires Clone, however, which is a little bit surplus to what we already have, but it's not a terribly onerous burden.
This question already has answers here:
How do you access enum values in Rust?
(6 answers)
Closed 2 years ago.
Here is code snippet, illustrating the problem:
pub enum Foo1 {
Bar(Foo2)
}
pub enum Foo2 {
Inner(Foo3)
}
pub struct Foo3 {
pub val: i32
}
fn main() {
let s2 = Foo1::Bar(Foo2::Inner(Foo3 { val: 5 }));
// println!("{}", s2.); // I want to print val field of Foo3 struct
}
How to do it without pattern matching?
Normally, I would reach for if let when you're only interested in one match branch:
if let Foo1::Bar(Foo2::Inner(foo3)) = s2 {
println!("{}", foo3.val);
}
Your case is unusual in that none of your enums have more than one element – the if would always be true, which would raise an "irrefutable_let_patterns" warning.
Rather than silencing this warning (for the particular statement), a direct let binding is enough:
let Foo1::Bar(Foo2::Inner(foo3)) = s2;
println!("{}", foo3.val);
Thanks, Sebastian Redl, for this tip!
I found what was looking for. Field destruction is what I needed.
if let Foo1::Bar(Foo2::Inner(Foo3{val:x})) = s2 {
println!("{}", x)
}
I'm new to Rust and I'm trying to figure out why Rc is behaving differently when being passed to a closure. My full code is the following:
use std::rc::Rc;
struct Something {
value: i32
}
fn main() {
let wrapped_struct = Some(Rc::new(Something { value: 1 }));
let wrapped_integer = Some(Rc::new(1));
// Case 1: This works
let works: Option<i32> = wrapped_struct.map(|i| { i.value });
// Case 2: This fails
let fails: Option<i32> = wrapped_integer.map(|i| { i });
}
The error message is:
|
13 | let fails: Option<i32> = wrapped_integer.map(|i| { i });
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected i32, found struct `std::rc::Rc`
|
= note: expected type `std::option::Option<i32>`
found type `std::option::Option<std::rc::Rc<{integer}>>`
What I don't understand is why in the first closure (Case 1) I can use i as a Something (I'd expect Rc<Something>) but in the second one (Case 2) I can't use i as an i32 (I actually get an Rc<i32>).
I appreciate any pointers to the relevant documentation. Thanks a lot!
The type of the i in both closures is actually Rc<Something> and Rc<i32> respectively. Rc can be dereferenced to access its inner data, but there are places in Rust where dereferencing happens automatically, for convenience.
In the struct case, when you write i.value, it will automatically dereference i to access the field. It then returns a copy of the i32, because i32 is a Copy type. So the type of the expression i.value is i32. It's as if you wrote (*i).value, but Rust did the dereferencing for you.
In the i32 case, you are just returning the i, which still has type Rc<i32>. You can fix it by explicitly dereferencing:
wrapped_integer.map(|i| { *i });
See also:
What are Rust's exact auto-dereferencing rules?