This question already has answers here:
How do I idiomatically convert a bool to an Option or Result in Rust?
(4 answers)
Closed last year.
The community reviewed whether to reopen this question last year and left it closed:
Original close reason(s) were not resolved
I have a closure in a filter_map that ends in this if statement:
if my_vec.is_empty() {
None
} else {
Some(my_vec)
}
Is there a simple way to convert an empty Vec into either a None or a Some(my_vec)?
There is a function in impl bool called then which converts a bool to an option.
let opt = (!my_vec.is_empty()).then(|| my_vec);
There is also then_some, available in nightly.
#![feature(bool_to_option)]
fn main() {
let my_vec: Vec<i32> = vec![];
let _opt = (!my_vec.is_empty()).then_some(my_vec);
}
Since you mentioned filter_map, what about changing
sth.filter_map(|item| {
let my_vec = some_operation(item);
if my_vec.is_empty() {
None
} else {
Some(my_vec)
}
})
to
sth
.map(|item| some_operation(item))
.filter( |vec| !vec.is_empty())
According to official doc, Rust's iterators are zero-cost abstraction, so you can do this without extra cost.
Related
This question already has answers here:
How do I extract a value from a tuple struct?
(3 answers)
Closed 5 months ago.
The community reviewed whether to reopen this question 5 months ago and left it closed:
Original close reason(s) were not resolved
With the below code snippet, Rustc gives the error cannot index into a value of type Matrix<T>.
What would be the proper way to access the vectors inside the Matrix struct in such cases?
pub struct Matrix<T>(pub Vec<Vec<T>>);
impl<T> Add for Matrix<T> {
fn add(self, other_matrix: Self) -> Option<Self> {
let mut vector_1 = vec![];
for x in 0..self.len() {
for y in 0..self[x].len() {
let total = self[x][y] + other_matrix[x][y];
vector_1.push(total);
}
// ... //
}
}
}
Any advice would be much appreciated!
You use identifier.order syntax to access a member of a tuple struct. In your case, it becomes self.0, and your snippet becomes like this:
for x in 0..self.0.len() {
for y in 0..self.0[x].len() {
let total = self.0[x][y] + other_matrix.0[x][y];
vector_1.push(total);
}
...
This question already has answers here:
How can I port C++ code that uses the ternary operator to Rust?
(3 answers)
How do I idiomatically convert a bool to an Option or Result in Rust?
(4 answers)
Closed 1 year ago.
In C, there is the conditional operator on the form int x = foo > bar ? 1 : 0;. According to this issue, that seems to be something the Rust developers do not want to implement. If one wants to be concise: Is there a Rust equivalent/shorthand version to do the same?
struct Config {
timeout: Option<u32>,
}
impl Config {
// C-style conditional operator
pub fn new(timeout: u32) {
Config {
timeout == 0 ? None : Some(timeout)
}
}
// My attempted Rust approach
pub fn new(timeout: u32) {
let mut t = None;
if timeout != 0 {
t = Some(timeout);
}
Config { timeout: t }
}
}
fn main() {
let config = Config::new(0);
}
I guess I have two problems with the Rust approach as of now: 1) I need to create a new variable which is very hard to name anything meaningful and 2) the code is less concise than the C-style conditional operator (though perhaps more explicit).
This question already has answers here:
What's the difference between placing "mut" before a variable name and after the ":"?
(4 answers)
Why does Rust allow mutation through a reference field using an immutable binding?
(1 answer)
Closed 2 years ago.
After a lot of struggle getting used to borrowing, references, ownership etc. and trying to follow the compiler's suggestions how to fix certain issues, I ended up with the following pair of functions in my first bit of Rust code.
fn adjust_culture(mut cooperating_families: Vec<&mut Family>) {
for f in cooperating_families.iter_mut() {
mutate_culture(f);
}
let family: Option<&&mut Family> = cooperating_families.choose(&mut rand::thread_rng());
match family {
None => {},
Some(f) => {
let target: Culture = f.culture;
for f2 in cooperating_families {
f2.culture = target;
}
}
}
}
fn mutate_culture(family: &mut Family) {
if family.seasons_till_next_mutation > 0 {
family.seasons_till_next_mutation -= 1;
}
if family.seasons_till_next_mutation == 0 {
let i: u8 = rand::thread_rng().gen_range(0, culture_dimensionality);
family.culture ^= 1 << i;
}
}
The second one makes sense to me, and preventing it from gaining additional borrowing decoration was a major point getting me to this solution. But adjust_culture confuses me: Why did the compiler suggest to add the mut before cooperating_families in the function's parameter definition?
I thought I would just have to pass a mutable binding to access the fields of the individual families, but with another function
fn extract_resources(patch: Patch, group: Vec<&mut Family>, total_labor_here: usize) -> KCal {
let labor: u8 = group.iter().map(|f| {f.effective_size as u8}).sum();
let resources_extracted = resources_from_patch(
patch, labor as usize, total_labor_here - labor as usize,
false);
for family in group {
family.stored_resources +=
resources_extracted * family.effective_size as f32 / labor as f32
}
return resources_extracted
}
Rust told me that group does not need to be mutable, and now I'm quite confused.
Which bit of adjust_culture has a chance to change the value of cooperating_families instead of just the objects inside it? How do I avoid that from happening – my mental idea of the semantics says is should not happen?
This question already has answers here:
Temporarily move out of borrowed content
(3 answers)
How can I swap in a new value for a field in a mutable reference to a structure?
(2 answers)
Closed 4 years ago.
I have an immutable data structure, and an update function that takes ownership of the data structure and returns a new data structure:
enum Immutable {
Item(i32)
}
fn update(imm: Immutable) -> Immutable {
match imm {
Immutable::Item(x) => Immutable::Item(x + 1)
}
}
I need to store the data structure in a mutable field of a container:
struct State {
item: Immutable
}
I want to write an imperative update function for State that calls the function updater:
fn update_mut(st: &mut State) -> () {
let mut owned = Immutable::Item(42); // junk
std::mem::swap(&mut st.item, &mut owned);
st.item = update(owned);
}
This code works, but it seems sily to use mem::swap and allocate a junk object. I would really like to write:
fn update_mut_type_error(st: &mut State) -> () {
let mut owned = Immutable::Item(42); // junk
std::mem::swap(&mut st.item, &mut owned);
st.item = update(st.item); // type error
}
Is there any way to address this? Or, do I have to use mem::swap here, even though it seems spurious.
Example on Rust Playground
As Sven points out, this question is answered here:
http://smallcultfollowing.com/babysteps/blog/2018/11/10/after-nll-moving-from-borrowed-data-and-the-sentinel-pattern/
This question already has answers here:
Why can't Rust infer the resulting type of Iterator::sum?
(2 answers)
Closed 4 years ago.
The following code is unable to deduce the type of s
fn main() {
let l: Vec<u32> = vec![];
let s = l.iter().sum();
println!("{:?}", s);
}
This is motivated by something in Rust by Example https://rustbyexample.com/std_misc/threads/testcase_mapreduce.html
// collect each thread's intermediate results into a new Vec
let mut intermediate_sums = vec![];
for child in children {
// collect each child thread's return-value
let intermediate_sum = child.join().unwrap();
intermediate_sums.push(intermediate_sum);
}
// combine all intermediate sums into a single final sum.
//
// we use the "turbofish" ::<> to provide sum() with a type hint.
//
// TODO: try without the turbofish, by instead explicitly
// specifying the type of intermediate_sums
let final_result = intermediate_sums.iter().sum::<u32>();
This seems to be implying that this should be possible. Or have I misinterpreted this suggestion?
N.B. I see some related ticket e.g., Why can't Rust infer the resulting type of Iterator::sum?, however in that case there is no type given for the sequence.
This seems to be implying that this should be possible. Or have I misinterpreted this suggestion?
I think it's a misinterpretation.
// TODO: try without the turbofish, by instead explicitly
// specifying the type of intermediate_sums
let final_result = intermediate_sums.iter().sum::<u32>();
It says you can do without the turbo fish by explicitly specifying the type, that is by doing:
let final_result: u32 = intermediate_sums.iter().sum();
In this respect, your main function can be written as:
fn main() {
let l: Vec<u32> = vec![];
let s: u32 = l.iter().sum();
println!("{:?}", s);
}