rust - all() - return false on empty iter - rust

Is there a way to make all() method return false on empty iter ?
example
let list = "";
let res = list.chars().all(|c| c == 'a');
println!("{}", res); // res here will print true and I want it to be false
I'm open for any other solution.

You will have to check on the string whether it is empty or not
let list = "";
let res = !list.is_empty() && list.chars().all(|c| c == 'a');
println!("{}", res); // res here will print false

We can use a trait to implement a new function all_not_empty() that returns true iff the predicate, i.e. the test function, matches all items of the iterator and the iterator is not empty. Then we implement this trait for all Iterators:
pub trait AllNotEmpty<T>: Iterator<Item = T> {
fn all_not_empty(&mut self, predicate: fn(T) -> bool) -> bool;
}
impl<T, I> AllNotEmpty<T> for I
where
I: Iterator<Item = T>,
{
fn all_not_empty(&mut self, predicate: fn(T) -> bool) -> bool {
match self.next() {
Some(item) => predicate(item) && self.all(predicate),
None => false,
}
}
}
fn main() {
let predicate = |c| c == 'a';
let empty = "";
let nonempty_false1 = "b";
let nonempty_false2 = "aba";
let nonempty_true = "aaa";
assert!(!empty.chars().all_not_empty(predicate));
assert!(!nonempty_false1.chars().all_not_empty(predicate));
assert!(!nonempty_false2.chars().all_not_empty(predicate));
assert!(nonempty_true.chars().all_not_empty(predicate));
}
The advantage of this is, that the trait can be used for any Iterator of any type and not only on objects that implement is_empty().

Related

Is there something similar to try_retain()?

Is it possible to apply FnMut(&mut V) -> Result<bool> for collection elements and if result is:
Ok(false) -- remove element and continue
Ok(true) -- leave element in collection and continue
Err(_) -- stop and return the error
Basically, how to code a try_retain(), an equivalent of this C++ code:
struct S {
// ...
};
// Updates `s` (and possibly some external state), returns true if `s` is no longer needed
// throws on error
bool bar(S& s);
void foo(std::map<int, S>& m) {
try
{
for(auto it = m.begin(), it_end = m.end(); it != it_end; ) {
if (bar(it->second))
m.erase(it++);
else
++it;
}
}
catch(...)
{
printf("bailed early\n");
throw;
}
}
For some reason I keep running into this pattern and I can't figure out how to do it in Rust without traversing collection twice or using additional memory...
This won't short-circuit, but you can do it by storing the global result in a mutable variable that's updated by the closure you pass to retain. Something like this:
use std::collections::HashMap;
fn try_retain<K, V, E, F>(m: &mut HashMap<K, V>, mut f: F) -> Result<(), E>
where
F: FnMut(&K, &mut V) -> Result<bool, E>,
{
let mut result = Ok(());
m.retain(|k, v| match f(k, v) {
Ok(b) => b,
Err(e) => {
result = Err(e);
true
}
});
return result;
}
Playground
If you're fine with switching to hashbrown::HashMap (which is what std::collections::HashMap uses as it's inner implementation), you could copy the implementation of fn retain and slightly change it to use the ? operator to return the first error:
fn try_retain<K, V, E, F>(m: &mut hashbrown::HashMap<K, V>, mut f: F) -> Result<(), E>
where
F: FnMut(&K, &mut V) -> Result<bool, E>,
{
let mut raw_table = m.raw_table();
// Here we only use `iter` as a temporary, preventing use-after-free
unsafe {
for item in raw_table.iter() {
let &mut (ref key, ref mut value) = item.as_mut();
if !f(key, value)? {
raw_table.erase(item);
}
}
}
Ok(())
}
This requires hashbrown's raw feature to be enabled, so you can access the underlying raw table.
This stops at the first error, and the elements are visited in a random order, so it's non-deterministic which elements are removed if an error occurs.
We could use try_for_each and remember the keys to remove (not to retain) till the end of the iteration because of the borrow checker:
fn try_retain(
map: &mut HashMap<i32, i32>,
to_retain: fn(k: i32, v: i32) -> bool,
) -> Result<bool, String> {
let mut to_remove: Vec<i32> = vec![];
map.iter().try_for_each(|(k, v)| {
if has_error() {
return Err("bailed early".to_string());
}
if !to_retain(*k, *v) {
to_remove.push(*k);
}
Ok::<_, String>(())
})?; // short-circuiting
if to_remove.is_empty() {
Ok(true)
} else {
(*map).retain(|&k, _| !to_remove.contains(&k));
Ok(false)
}
}
The return value results from whether there are keys to remove.
Can short-circuiting.
Playground
If the extra space for the to-remove-items is still too much, here is an unstable solution with drain_filter:
fn try_retain(
map: &mut HashMap<i32, i32>,
to_retain: fn(k: i32, v: i32) -> bool,
) -> bool {
let mut rslt = true;
map.drain_filter(|k, v| {
if !to_retain(*k, *v) {
rslt = false;
true
} else {
false
}
});
rslt
}
Short-circuiting is only possible through panic.
Playground

How can I intersperse a rust iterator with a value every n items?

I have an iterator of characters, and I want to add a newline every N characters:
let iter = "abcdefghijklmnopqrstuvwxyz".chars();
let iter_with_newlines = todo!();
let string: String = iter_with_newlines.collect();
assert_eq("abcdefghij\nklmnopqrst\nuvwxyz", string);
So basically, I want to intersperse the iterator with a newline every n characters. How can I do this?
Some Ideas I had
It would be great if I could do something like this, where chunks would be a method to make Iterator<T> into Iterator<Iterator<T>: iter.chunks(10).intersperse('\n').flatten()
It would also be cool if I could do something like this: iter.chunks.intersperseEvery(10, '\n'), where intersperseEvery is a method that would only intersperse the value every n items.
You can do it without temporary allocation using enumerate and flat_map:
use either::Either;
fn main() {
let iter = "abcdefghijklmnopqrstuvwxyz".chars();
let iter_with_newlines = iter
.enumerate()
.flat_map(|(i, c)| {
if i % 10 == 0 {
Either::Left(['\n', c].into_iter())
} else {
Either::Right(std::iter::once(c))
}
})
.skip(1); // The above code add a newline in first position -> skip it
let string: String = iter_with_newlines.collect();
assert_eq!("abcdefghij\nklmnopqrst\nuvwxyz", string);
}
Playground
Here's what I ended up doing:
// src/intersperse_sparse.rs
use core::iter::Peekable;
/// An iterator adaptor to insert a particular value
/// every n elements of the adapted iterator.
///
/// Iterator element type is `I::Item`
pub struct IntersperseSparse<I>
where
I: Iterator,
I::Item: Clone,
{
iter: Peekable<I>,
step_length: usize,
index: usize,
separator: I::Item,
}
impl<I> IntersperseSparse<I>
where
I: Iterator,
I::Item: Clone,
{
#[allow(unused)] // Although this function isn't explicitly exported, it is called in the default implementation of the IntersperseSparseAdapter, which is exported.
fn new(iter: I, step_length: usize, separator: I::Item) -> Self {
if step_length == 0 {
panic!("Chunk size cannot be 0!")
}
Self {
iter: iter.peekable(),
step_length,
separator,
index: 0,
}
}
}
impl<I> Iterator for IntersperseSparse<I>
where
I: Iterator,
I::Item: Clone,
{
type Item = I::Item;
fn next(&mut self) -> Option<Self::Item> {
if self.index == self.step_length && self.iter.peek().is_some() {
self.index = 0;
Some(self.separator.clone())
} else {
self.index += 1;
self.iter.next()
}
}
}
/// An iterator adaptor to insert a particular value created by a function
/// every n elements of the adapted iterator.
///
/// Iterator element type is `I::Item`
pub struct IntersperseSparseWith<I, G>
where
I: Iterator,
G: FnMut() -> I::Item,
{
iter: Peekable<I>,
step_length: usize,
index: usize,
separator_closure: G,
}
impl<I, G> IntersperseSparseWith<I, G>
where
I: Iterator,
G: FnMut() -> I::Item,
{
#[allow(unused)] // Although this function isn't explicitly exported, it is called in the default implementation of the IntersperseSparseAdapter, which is exported.
fn new(iter: I, step_length: usize, separator_closure: G) -> Self {
if step_length == 0 {
panic!("Chunk size cannot be 0!")
}
Self {
iter: iter.peekable(),
step_length,
separator_closure,
index: 0,
}
}
}
impl<I, G> Iterator for IntersperseSparseWith<I, G>
where
I: Iterator,
G: FnMut() -> I::Item,
{
type Item = I::Item;
fn next(&mut self) -> Option<Self::Item> {
if self.index == self.step_length && self.iter.peek().is_some() {
self.index = 0;
Some((self.separator_closure)())
} else {
self.index += 1;
self.iter.next()
}
}
}
/// Import this trait to use the `iter.intersperse_sparse(n, item)` and `iter.intersperse_sparse(n, ||item)` on all iterators.
pub trait IntersperseSparseAdapter: Iterator {
fn intersperse_sparse(self, chunk_size: usize, separator: Self::Item) -> IntersperseSparse<Self>
where
Self: Sized,
Self::Item: Clone,
{
IntersperseSparse::new(self, chunk_size, separator)
}
fn intersperse_sparse_with<G>(
self,
chunk_size: usize,
separator_closure: G,
) -> IntersperseSparseWith<Self, G>
where
Self: Sized,
G: FnMut() -> Self::Item,
{
IntersperseSparseWith::new(self, chunk_size, separator_closure)
}
}
impl<I> IntersperseSparseAdapter for I where I: Iterator {}
To use it:
// src/main.rs
mod intersperse_sparse;
use intersperse_sparse::IntersperseSparseAdapter;
fn main() {
let string = "abcdefg";
let new_string: String = string.chars().intersperse_sparse(3, '\n').collect();
assert_eq!(new_string, "abc\ndef\ng");
}
If you don't particularly care about performance, you can use chunks from itertools, collect the chunks into Vecs, and then intersperse your element as a single-element Vec, just to flatten the whole thing finally.
use itertools::Itertools;
iter
.chunks(3)
.into_iter()
.map(|chunk| chunk.collect::<Vec<_>>())
.intersperse(vec![','])
.flat_map(|chunk| chunk.into_iter())
.collect::<String>();
Playground
Other than that, consider writing your own iterator extension trait, just like itertools is one?
Build an Iterator with from_fn:
let mut iter = "abcdefghijklmnopqrstuvwxyz".chars().peekable();
let mut count = 0;
let iter_with_newlines = std::iter::from_fn(move || match iter.peek() {
Some(_) => {
if count < 10 {
count += 1;
iter.next()
} else {
count = 0;
Some('\n')
}
}
None => None,
});
assert_eq!(
"abcdefghij\nklmnopqrst\nuvwxyz",
iter_with_newlines.collect::<String>()
);
Playground

What am I doing wrong in this code to implement a `dequeue` function for a queue?

I'm trying to implement a dequeue function for a queue but I am confused how the borrow checker works. What am I doing wrong in this code?
use std::cell::RefCell;
use std::rc::Rc;
use std::mem::replace;
type Link<T> = Option<Rc<RefCell<Node<T>>>>;
struct Node<T>{
item: T,
next: Link<T>
}
pub struct Queue<T>{
first: Link<T>,
last: Link<T>,
length: usize
}
impl<T> Queue<T>{
pub fn new() -> Queue<T> {
Queue {
first: None,
last: None,
length: 0
}
}
pub fn is_empty(&self) -> bool {
self.length == 0
}
pub fn size(&self) -> usize {
self.length
}
pub fn enqueue(&mut self, item: T) {
let temp = self.last.take();
self.last = Some(Rc::new(RefCell::new(Node{
item,
next: None
})));
if self.is_empty() {
self.first = self.last.clone();
} else {
let temp = temp.unwrap();
temp.borrow_mut().next = self.last.clone();
}
self.length += 1;
}
pub fn dequeue(&mut self) -> Result<T, String>{
if let Some(ref mut value) = self.first.take() {
let mut temp = *(value.borrow_mut());
let next = *(temp.next.unwrap().borrow_mut());
let old_value = replace(&mut temp, next);
return Ok(old_value.item);
}
Err("Queue is empty".to_owned())
}
}
Having obtained a mutable reference to the value inside Some, I want to replace with the node that is being referenced by the next field of the node. Do I need to take ownership of the value inside Some? Can I even do that?
Here is an implementation of the dequeue:
pub fn dequeue(&mut self) -> Result<T, String> {
// First, disconnect `self.last` from the element it is pointing,
// since it will have to be updated anyway. If there is no elemen in the
// queue, we're done.
let first = try!(self.first.take().ok_or("Queue is empty".to_owned()));
// if there are two Rc's pointing to this node, then this must be the
// only node, so `self.last` has to go
if Rc::strong_count(&first) == 2 {
self.last = None;
}
let first_node = Rc::try_unwrap(first).ok().expect(
"This should be the only owner of the node"
).into_inner();
self.first = first_node.next;
self.length -= 1;
Ok(first_node.item)
}
Here is the complete code. I also added a dequeue_back for making this almost a double ended queue and some tests.

Change selector in match when selector is a mutable reference

I want to change enum variant based on some properties of the current enum variant in Iterator::next. I have two attempts, neither of which compile:
enum Test {
A(Vec<usize>),
B,
}
impl<'a> Iterator for Test {
type Item = usize;
fn next(&mut self) -> Option<Self::Item> {
// attempt 1
if let Test::A(ref a) = *self {
if a.len() == 0 {
*self = Test::B; // doesn't work because a is borrowed
};
}
// attempt 2
*self = match *self {
Test::A(ref a) if a.len() == 0 => Test::B,
_ => *self, // cannot move out of borrowed context
};
None
}
}
fn main() {}
My second attempt does work if I am not working with references in the selector:
let mut a = Test::A(vec![]);
a = match a {
Test::A(ref a) if a.len() == 0 => Test::B,
_ => a,
};
This question is related to Is there a way to use match() in rust when modifying the selector?, but the solution proposed there is not generic: it only works if the same function is executed in both branches.
What is the Rustacean way to achieve my goal?
Since the condition is not very readable when put inside an if let / match block, I would just use a helper function to test for it:
impl Test {
fn is_empty_a(&self) -> bool {
if let Test::A(ref a) = *self {
a.len() == 0
} else {
false
}
}
}
And then there shouldn't be any borrowing issues:
impl<'a> Iterator for Test {
type Item = usize;
fn next(&mut self) -> Option<Self::Item> {
if self.is_empty_a() {
*self = Test::B;
}
None
}
}

What is the right way to share a reference between closures if the value outlives the closures?

I want to share a reference between two closures; mutably in one closure. This is an artificial situation, but I find it interesting in the context of learning Rust.
In order to make it work, I had to make use of Rc, Weak, and RefCell. Is there a simpler way of achieving this?
use std::cell::RefCell;
use std::rc::Rc;
#[derive(Debug)]
struct Foo {
i: i32,
}
impl Foo {
fn get(&self) -> i32 {
self.i
}
fn incr(&mut self) {
self.i += 1
}
}
fn retry<O, N>(mut operation: O, mut notify: N) -> i32
where
O: FnMut() -> i32,
N: FnMut() -> (),
{
operation();
notify();
operation()
}
fn something(f: &mut Foo) {
let f_rc = Rc::new(RefCell::new(f));
let f_weak = Rc::downgrade(&f_rc);
let operation = || {
// f.get()
let cell = f_weak.upgrade().unwrap();
let f = cell.borrow();
f.get()
};
let notify = || {
// f.incr();
let cell = f_weak.upgrade().unwrap();
let mut f = cell.borrow_mut();
f.incr();
};
retry(operation, notify);
println!("{:?}", f_rc);
}
fn main() {
let mut f = Foo { i: 1 };
something(&mut f);
}
Reference counting is unnecessary here because the entity lives longer than any of the closures. You can get away with:
fn something(f: &mut Foo) {
let f = RefCell::new(f);
let operation = || f.borrow().get();
let notify = || {
f.borrow_mut().incr();
};
retry(operation, notify);
println!("{:?}", f);
}
which is quite simpler.
The use of RefCell, however, is necessary to move the enforcement of the Aliasing XOR Mutability from compile-time to run-time.

Resources