I am mapping over Vec such that each item becomes a Result. If any element is an Err then I want to terminate early and produce an Err, otherwise I want to produce an Ok containing the Vec<i32>.
let v = (1..10)
.map( |n| {
if n % 4 == 0 {
Err("Too fourish!")
}
else {
Ok(n)
}
}).collect::<Vec<_>>();
println!("{:?}", v);
In Haskell, I can use sequence. Is there an equivalent built-in Rust function?
You can use the FromIterator implementation of Result for this:
fn main() {
let v = (1..10)
.map( |n| {
if n % 4 == 0 {
Err("Too fourish!")
}
else {
Ok(n)
}
}).collect::<Result<Vec<_>, _>>();
println!("{:?}", v);
let v = (1..10)
.map( |n| {
if n % 4 == 4 { // impossible
Err("Too fourish!")
}
else {
Ok(n)
}
}).collect::<Result<Vec<_>, _>>();
println!("{:?}", v);
}
Output:
Err("Too fourish!")
Ok([1, 2, 3, 4, 5, 6, 7, 8, 9])
More info: https://doc.rust-lang.org/std/result/enum.Result.html#implementations
Related
I have a struct, lets call it A and an enum E.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum E {
Val1,
Val2,
Val3,
Val4,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
struct A {
a: u64,
b: u64,
}
I implemented the Index trait as:
impl Index<usize> for A {
type Output = E;
fn index(&self, index: usize) -> &Self::Output {
match ((self.a >> index) & 1, (self.b >> index) & 1) {
(0, 0) => &E::Val1,
(0, 1) => &E::Val2,
(1, 0) => &E::Val3,
(1, 1) => &E::Val4,
_ => unreachable!(),
}
}
}
I have a method set_val on A.
impl A {
pub fn set_val(&mut self, idx: usize, val: E) {
match val {
E::Val1 => {
self.a &= !1 << idx;
self.b &= !1 << idx;
}
E::Val2 => {
self.a &= !1 << idx;
self.b |= 1 << idx;
}
E::Val3 => {
self.a |= 1 << idx;
self.b &= !1 << idx;
}
E::Val4 => {
self.a |= 1 << idx;
self.b |= 1 << idx;
}
}
}
}
I want to know how I could implement set_val using IndexMut, so that I can do:
let mut a = A {a: 0, b: 0};
a[4] = E::Val3;
// instead of
a.set_val(4, E::Val3);
As #rodrigo have pointed out in the comments, IndexMut returns a mutable reference. This way, you can do things like &mut slice[index] to get a mutable reference to the element at the given index, which already exists in memory.
However, you are creating and returning an instance of E here. Writing to that value will not update the original a and b variables. This is because once you return from index_mut, you no longer have access to self, and cannot update any variables; the caller is supposed to simply write to the mutable reference you returned, which in this case would do nothing.
As #eggyal pointed out, this might be possible with the proposed IndexSet trait, which could look something like this (my idea based on this postponed PR):
trait IndexSet<Index, Rhs> {
/// `self[index] = rhs`
fn index_set(&mut self, index: Index, rhs: Rhs);
}
Then you could implement it like this, nearly identically to your set_val method:
impl IndexSet<usize, E> for A {
pub fn index_set(&mut self, idx: usize, val: E) {
match val {
E::Val1 => {
self.a &= !1 << idx;
self.b &= !1 << idx;
}
E::Val2 => {
self.a &= !1 << idx;
self.b |= 1 << idx;
}
E::Val3 => {
self.a |= 1 << idx;
self.b &= !1 << idx;
}
E::Val4 => {
self.a |= 1 << idx;
self.b |= 1 << idx;
}
}
}
}
Fingers crossed that this feature will work out.
For example I have such a simple task: count all raws and columns which have all zeros in 2D array.
So for
0 0 0
0 0 0
1 0 1
answer is 2 raws and 1 column.
I can make it just like that for raws: var cntRaws = a.count { it.all { el -> el == 0 } }, but how to solve it for columns in same way?
val x = Array<IntArray>(3) { IntArray(3) { 0 } }
x[2][0] = 1
x[2][2] = 1
val raws = x.count { it.sum() == 0 }
val columns = (x.indices)
.map { columnIndex -> x.map { it[columnIndex] } }
.count { it.sum() == 0 }
println("total raws:$raws")
println("total col:$columns")
I couldn't think of any idomatic / functional style to do this, but I came up with an idea just create a lazily evaluated swapping function that swaps the columns with rows when it wants to pull without creating a new list.
fun <T> List<List<T>>.swapped() = sequence {
var index = 0
while (index < size) {
yield(map { it[index] })
index++
}
}
fun main() {
val list = listOf(
listOf(0, 0, 0),
listOf(0, 0, 0),
listOf(1, 0, 1)
)
val cntRows = list.count { it.all { el -> el == 0 } }
val cntCols = list.swapped().count { it.all { el -> el == 0 } }
println("cntRows: $cntRows")
println("cntCols: $cntCols")
}
I tried my best to optimize it and do it in same O(n*m) steps as done with the regular row counting, since Sequences are lazily evaluated.
This is a functional way of doing it that works if all rows are the same size:
fun <T>List<List<T>>.rowToColumn() = (0 until first().size).map{row -> (0 until size).map {col-> this[col][row] }}
I need to find only the numbers where the next number is the same: [1,2,2,3,4,4] should produce [2,4]. Since I need to peek at the next number, I figured I'd try out using a Peekable iterator and write a filter.
fn main() {
let xs = [1, 2, 2, 3, 4, 4];
let mut iter = xs.iter().peekable();
let pairs = iter.filter(move |num| {
match iter.peek() {
Some(next) => num == next,
None => false,
}
});
for num in pairs {
println!("{}", num);
}
}
I get an error:
error[E0382]: capture of moved value: `iter`
--> src/main.rs:6:15
|
5 | let pairs = iter.filter(move |num| {
| ---- value moved here
6 | match iter.peek() {
| ^^^^ value captured here after move
|
= note: move occurs because `iter` has type `std::iter::Peekable<std::slice::Iter<'_, i32>>`, which does not implement the `Copy` trait
I think this is because iter is being used by the closure, but it hasn't borrowed it, and it can't copy it.
How do I solve this problem of wanting to refer to the iterator inside a filter?
refer to the iterator inside a filter
I don't believe you can. When you call filter, it takes ownership of the base iterator:
fn filter<P>(self, predicate: P) -> Filter<Self, P>
where
P: FnMut(&Self::Item) -> bool,
Once you do that, it's gone. There is no more iter. In some similar cases, you can use Iterator::by_ref to mutably borrow the iterator, drive it for a while, then refer back to the original. That won't work in this case because the inner iterator would need to borrow it mutably a second time, which is disallowed.
find only the numbers where the next number is the same.
extern crate itertools;
use itertools::Itertools;
fn main() {
let input = [1, 2, 2, 3, 4, 4];
let pairs = input
.iter()
.tuple_windows()
.filter_map(|(a, b)| if a == b { Some(a) } else { None });
let result: Vec<_> = pairs.cloned().collect();
assert_eq!(result, [2, 4]);
}
Or if you wanted something using only the standard library:
fn main() {
let xs = [1, 2, 2, 3, 4, 4];
let mut prev = None;
let pairs = xs.iter().filter_map(move |curr| {
let next = if prev == Some(curr) { Some(curr) } else { None };
prev = Some(curr);
next
});
let result: Vec<_> = pairs.cloned().collect();
assert_eq!(result, [2, 4]);
}
The program aims to use a loop to check if the index of a iterator variable meets certain criteria (i.g., index == 3). If find the desired index, return Some(123), else return None.
fn main() {
fn foo() -> Option<i32> {
let mut x = 5;
let mut done = false;
while !done {
x += x - 3;
if x % 5 == 0 {
done = true;
}
for (index, value) in (5..10).enumerate() {
println!("index = {} and value = {}", index, value);
if index == 3 {
return Some(123);
}
}
return None; //capture all other other possibility. So the while loop would surely return either a Some or a None
}
}
}
The compiler gives this error:
error[E0308]: mismatched types
--> <anon>:7:9
|
7 | while !done {
| ^ expected enum `std::option::Option`, found ()
|
= note: expected type `std::option::Option<i32>`
= note: found type `()`
I think the error source might be that a while loop evaluates to a (), thus it would return a () instead of Some(123). I don't know how to return a valid Some type inside a loop.
The value of any while true { ... } expression is always (). So the compiler expects your foo to return an Option<i32> but finds the last value in your foo body is ().
To fix this, you can add a return None outside the original while loop. You can also use the loop construct like this:
fn main() {
// run the code
foo();
fn foo() -> Option<i32> {
let mut x = 5;
loop {
x += x - 3;
for (index, value) in (5..10).enumerate() {
println!("index = {} and value = {}", index, value);
if index == 3 {
return Some(123);
}
}
if x % 5 == 0 {
return None;
}
}
}
}
The behaviour of while true { ... } statements is maybe a bit quirky and there have been a few requests to change it.
I'd like to remove some elements from a Vec, but vec.iter().filter().collect() creates a new vector with borrowed items.
I'd like to mutate the original Vec without extra memory allocation (and keep memory of removed elements as an extra capacity of the vector).
If you want to remove elements, you can use retain(), which removes elements from the vector if the closure returns false:
let mut vec = vec![1, 2, 3, 4];
vec.retain(|&x| x % 2 == 0);
assert_eq!(vec, [2, 4]);
If you want to modify the elements in place, you have to do that in a for x in vec.iter_mut().
If you truly want to mutate the vector's elements while filtering it, you can use the nightly-only method Vec::drain_filter, an extremely flexible tool:
#![feature(drain_filter)]
fn main() {
let mut vec = vec![1, 2, 3, 4];
vec.drain_filter(|x| {
if *x % 2 == 0 {
true
} else {
*x += 100;
false
}
});
assert_eq!(vec, [101, 103]);
}
It also allows you to get the removed elements as the return value of the entire method is an iterator!
Till Vec::drain_filter gets stable, we can solve the problem with homebrewed rust:
fn main() {
let mut v = vec![1, 2, 3, 4];
let mut i = 0;
while i < v.len() {
if v[i] % 2 == 0 {
v.remove(i);
} else {
v[i] += 100;
i += 1;
}
}
println!("{:?}", v); // [101, 103]
}
BTW remove() is an O(n) operation but doesn't allocate memory.
Playground
I am providing my take for this problem as I was unaware of the retain method:
impl<T> RemoveFilter<T> for Vec<T> {}
pub trait RemoveFilter<T>: BorrowMut<Vec<T>> {
fn remove_filter<F: for<'b> FnMut(&'b T) -> bool>(&mut self, mut cb: F) {
let vec: &mut Vec<T> = self.borrow_mut();
let mut write_to = 0;
let mut read_from = 0;
while read_from < vec.len() {
let maintain = cb(&mut vec[read_from]);
if maintain {
vec.as_mut_slice().swap(read_from, write_to);
write_to += 1;
}
read_from += 1;
}
vec.resize_with(write_to, || panic!("We are shrinking the vector"));
}
}
It will shift the elements as it iterates and then remove anything that is left behind. I think this is code may easily modified to solve other problems.