Rust trait and its default implementation - traits

Wrote a trait that checks a given number(u16 or u32) is even or not.
v1.0
trait EvenOdd {
fn is_even(&self) -> bool;
}
impl EvenOdd for u16 {
fn is_even(&self) -> bool {
self % 2 == 0
}
}
impl EvenOdd for u32 {
fn is_even(&self) -> bool {
self % 2 == 0
}
}
fn main() {
let x: u16 = 11;
let y: u32 = 44;
println!("x = {}, y = {}", x.is_even(), y.is_even());
}
This runs fine. But since is_even is repeated for u16 and u32, moved it into the trait as a default method.
v2.0
trait EvenOdd {
fn is_even(&self) -> bool {
self % 2 == 0
}
}
impl EvenOdd for u16 {
}
impl EvenOdd for u32 {
}
fn main() {
let x: u16 = 11;
let y: u32 = 44;
println!("x = {}, y = {}", x.is_even(), y.is_even());
}
This produces compiler error:
error[E0369]: binary operation `%` cannot be applied to type `&Self`
--> trait_arithmetic_v2.rs:3:9
|
3 | self % 2 == 0
| ^^^^^^^^
|
= note: an implementation of `std::ops::Rem` might be missing for `&Self`
Attempting to constrain &self results in compiler error:
fn is_even<T: std::ops::Rem> (&self: T) -> bool
self % 2 == 0
}
error: expected one of `)` or `,`, found `:`
--> trait_arithmetic_v2.rs:2:44
|
2 | fn is_even<T: std::ops::Rem> (&self: T) -> bool {
| ^ expected one of `)` or `,` here
The only way I could apply the constraint is by changing the is_even api.
v3.0
use std::ops::Rem;
trait EvenOdd {
fn is_even<T: Rem<Output = T> + PartialEq + From<u8>> (&self, other: T) -> bool {
other % 2.into() == 0.into()
}
}
And use it like x.is_even(x) which is un-natural. How to fix my v2.0? Thanks.

In v2.0 the compiler don't know the type that you are trying to apply the arithmetic operation and trait EvenOdd: Rem doesn't work because Rem takes Self.
This code is somewhat limited but works for your example and it is functional because there is a default implementation of impl From<u16> for u32.
use std::ops::Rem;
trait EvenOdd {
fn is_even(&self) -> bool;
}
impl<T> EvenOdd for T
where
T: Copy + From<u16> + PartialEq + Rem<Output=T>
{
fn is_even(&self) -> bool {
*self % From::from(2u16) == From::from(0u16)
}
}
fn main() {
let x: u16 = 11;
let y: u32 = 44;
println!("x = {}, y = {}", x.is_even(), y.is_even());
}

Related

How can I return an iterator over a locked struct member in Rust?

Here is as far as I could get, using rental, partly based on How can I store a Chars iterator in the same struct as the String it is iterating on?. The difference here is that the get_iter method of the locked member has to take a mutable self reference.
I'm not tied to using rental: I'd be just as happy with a solution using reffers or owning_ref.
The PhantomData is present here just so that MyIter bears the normal lifetime relationship to MyIterable, the thing being iterated over.
I also tried changing #[rental] to #[rental(deref_mut_suffix)] and changing the return type of MyIterable.get_iter to Box<Iterator<Item=i32> + 'a> but that gave me other lifetime errors originating in the macro that I was unable to decipher.
#[macro_use]
extern crate rental;
use std::marker::PhantomData;
pub struct MyIterable {}
impl MyIterable {
// In the real use-case I can't remove the 'mut'.
pub fn get_iter<'a>(&'a mut self) -> MyIter<'a> {
MyIter {
marker: PhantomData,
}
}
}
pub struct MyIter<'a> {
marker: PhantomData<&'a MyIterable>,
}
impl<'a> Iterator for MyIter<'a> {
type Item = i32;
fn next(&mut self) -> Option<i32> {
Some(42)
}
}
use std::sync::Mutex;
rental! {
mod locking_iter {
pub use super::{MyIterable, MyIter};
use std::sync::MutexGuard;
#[rental]
pub struct LockingIter<'a> {
guard: MutexGuard<'a, MyIterable>,
iter: MyIter<'guard>,
}
}
}
use locking_iter::LockingIter;
impl<'a> Iterator for LockingIter<'a> {
type Item = i32;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
self.rent_mut(|iter| iter.next())
}
}
struct Access {
shared: Mutex<MyIterable>,
}
impl Access {
pub fn get_iter<'a>(&'a self) -> Box<Iterator<Item = i32> + 'a> {
Box::new(LockingIter::new(self.shared.lock().unwrap(), |mi| {
mi.get_iter()
}))
}
}
fn main() {
let access = Access {
shared: Mutex::new(MyIterable {}),
};
let iter = access.get_iter();
let contents: Vec<i32> = iter.take(2).collect();
println!("contents: {:?}", contents);
}
As user rodrigo has pointed out in a comment, the solution is simply to change #[rental] to #[rental_mut].

How can a function conditionally fall back to a trait if another trait is implemented or not?

I am building up a library for generating the minimum perfect hash from a set of keys. The idea is to index the keys online without storing the full dataset in memory. Based on a user requirement, it is possible that skip_next() is not available and I want to fall back to using next(). Although it might be slower based on the speed of the iterator, it simplifies things for a general user.
My idea is to selectively iterate over all the elements generated by an iterator. This code works fine, but it requires a user to implement the trait FastIteration:
#[derive(Debug)]
struct Pixel {
r: Vec<i8>,
g: Vec<i8>,
b: Vec<i8>,
}
#[derive(Debug)]
struct Node {
r: i8,
g: i8,
b: i8,
}
struct PixelIterator<'a> {
pixel: &'a Pixel,
index: usize,
}
impl<'a> IntoIterator for &'a Pixel {
type Item = Node;
type IntoIter = PixelIterator<'a>;
fn into_iter(self) -> Self::IntoIter {
println!("Into &");
PixelIterator {
pixel: self,
index: 0,
}
}
}
impl<'a> Iterator for PixelIterator<'a> {
type Item = Node;
fn next(&mut self) -> Option<Node> {
println!("next &");
let result = match self.index {
0 | 1 | 2 | 3 => Node {
r: self.pixel.r[self.index],
g: self.pixel.g[self.index],
b: self.pixel.b[self.index],
},
_ => return None,
};
self.index += 1;
Some(result)
}
}
trait FastIteration {
fn skip_next(&mut self);
}
impl<'a> FastIteration for PixelIterator<'a> {
fn skip_next(&mut self) {
self.index += 1;
}
}
fn main() {
let p1 = Pixel {
r: vec![11, 21, 31, 41],
g: vec![12, 22, 32, 42],
b: vec![13, 23, 33, 43],
};
let mut index = 0;
let mut it = p1.into_iter();
loop {
if index == p1.r.len() {
break;
}
if index == 1 {
it.skip_next()
} else {
let val = it.next();
println!("{:?}", val);
}
index += 1;
}
}
How can one make the above program fall back to using the normal next() instead of skip_next() based on if the trait FastIteration is implemented or not?
fn fast_iterate<I>(objects: I)
where I: IntoIter + FastIteration { // should use skip_next() };
fn slow_iterate<I>(objects: I)
where I: IntoIter { // should NOT use skip_next(), use next() };
As above, one can always write two separate impl but is it possible to do this in one?
This question builds on:
Conditionally implement a Rust trait only if a type constraint is satisfied
Implement rayon `as_parallel_slice` using iterators.
You are looking for the unstable feature specialization:
#![feature(specialization)]
#[derive(Debug)]
struct Example(u8);
impl Iterator for Example {
type Item = u8;
fn next(&mut self) -> Option<u8> {
let v = self.0;
if v > 10 {
None
} else {
self.0 += 1;
Some(v)
}
}
}
trait FastIterator: Iterator {
fn skip_next(&mut self);
}
impl<I: Iterator> FastIterator for I {
default fn skip_next(&mut self) {
println!("step");
self.next();
}
}
impl FastIterator for Example {
fn skip_next(&mut self) {
println!("skip");
self.0 += 1;
}
}
fn main() {
let mut ex = Example(0);
ex.skip_next();
let mut r = 0..10;
r.skip_next();
}

What is the proper way to pass a module as an argument?

I have a module file (src/map/map.rs):
type Layer = Vec<Vec<Tile>>;
pub struct Map {
height: i32,
width: i32,
data: Layer,
rooms: Vec<Rect>,
}
impl Map {
pub fn new(width: i32, height: i32) -> Self {
Map {
height: height,
width: width,
data: vec![vec![Tile::wall(); height as usize]; width as usize],
rooms: vec![Rect],
}
}
pub fn generate_with(&self, creator: module) {
creator::generate(&self)
}
}
a nested module map::gen::dungeon::basic (src/map/gen/dungeon/basic.rs)
with one function in the file:
pub fn generate(map: &mut Map) -> (Map, (i32, i32)) {}
and the map module file (src/map/mod.rs):
mod rect;
mod tile;
mod map;
pub mod room;
pub mod gen;
pub use self::map::Map;
pub use self::rect::Rect;
pub use self::tile::Tile;
imported into main.rs like this:
mod map;
use map::*;
use map::gen;
I want to be able to use it like this:
let (map, (player_x, player_y)) = Map::new(MAP_WIDTH, MAP_HEIGHT).generate_with(gen::dungeon::basic);
the error I get though is:
[cargo] expected value, found module 'gen::dungeon::basic': not a value [E]
A complete repo is available.
As stated in the comments, a module is not a concrete concept like that; what you are attempting to do is not possible.
Instead, you can pass something that can be a value:
mod basic {
pub fn generate() -> u8 {
0
}
}
mod advanced {
pub fn generate() -> u8 {
42
}
}
fn play_the_game(generator: fn() -> u8) {
let dungeon = generator();
println!("{}", dungeon);
}
fn main() {
play_the_game(basic::generate);
play_the_game(advanced::generate);
}
You could also introduce a trait and pass the implementing type as a generic:
trait DungeonGenerator {
fn generate() -> u8;
}
mod basic {
use DungeonGenerator;
pub struct Basic;
impl DungeonGenerator for Basic {
fn generate() -> u8 {
0
}
}
}
mod advanced {
use DungeonGenerator;
pub struct Advanced;
impl DungeonGenerator for Advanced {
fn generate() -> u8 {
42
}
}
}
fn play_the_game<G>()
where
G: DungeonGenerator,
{
let dungeon = G::generate();
println!("{}", dungeon);
}
fn main() {
play_the_game::<basic::Basic>();
play_the_game::<advanced::Advanced>();
}

Rust iterators and looking forward (peek/multipeek)

I am trying to use a pattern with iterators in Rust and falling down somewhere, apparently simple.
I would like to iterate through a container and find an element with a predicate [A] (simple), but then look forward using another predicate and get that value [B] and use [B] to mutate [A] in some way. In this case [A] is mutable and [B] can be immutable; this makes no difference to me, only to the borrow checker (rightly).
It would help to understand this with a simple scenario, so I have added a small snippet to let folk see the issue/attempted goal. I have played with itertools and breaking into for/while loops, although I want to remain as idiomatic as possible.
Silly Example scenario
Lookup an even number, find next number that is divisible by 3 and add to the initial number.
#[allow(unused)]
fn is_div_3(num: &u8) -> bool {
num % 3 == 0
}
fn main() {
let mut data: Vec<u8> = (0..100).collect();
let count = data.iter_mut()
.map(|x| {
if *x % 2 == 0 {
// loop through numbers forward to next is_div_3,
// then x = x + that number
}
true
})
.count();
println!("data {:?}, count was {} ", data, count);
}
playground
Sadly I'm a bit late, but here goes.
It's not totally pretty, but it's not as bad as the other suggestion:
let mut data: Vec<u8> = (1..100).collect();
{
let mut mut_items = data.iter_mut();
while let Some(x) = mut_items.next() {
if *x % 2 == 0 {
let slice = mut_items.into_slice();
*x += *slice.iter().find(|&x| x % 3 == 0).unwrap();
mut_items = slice.iter_mut();
}
}
}
println!("{:?}", data);
gives
[1, 5, 3, 10, 5, 15, 7, 17, 9, 22, ...]
as with Matthieu M.'s solution.
The key is to use mut_items.into_slice() to "reborrow" the iterator, effectively producing a local (and thus safe) clone of the iterator.
Warning: The iterator presented right below is unsafe because it allows one to obtain multiple aliases to a single mutable element; skip to the second part for the corrected version. (It would be alright if the return type contained immutable references).
If you are willing to write your own window iterator, then it becomes quite easy.
First, the iterator in all its gory details:
use std::marker::PhantomData;
struct WindowIterMut<'a, T>
where T: 'a
{
begin: *mut T,
len: usize,
index: usize,
_marker: PhantomData<&'a mut [T]>,
}
impl<'a, T> WindowIterMut<'a, T>
where T: 'a
{
pub fn new(slice: &'a mut [T]) -> WindowIterMut<'a, T> {
WindowIterMut {
begin: slice.as_mut_ptr(),
len: slice.len(),
index: 0,
_marker: PhantomData,
}
}
}
impl<'a, T> Iterator for WindowIterMut<'a, T>
where T: 'a
{
type Item = (&'a mut [T], &'a mut [T]);
fn next(&mut self) -> Option<Self::Item> {
if self.index > self.len { return None; }
let slice: &'a mut [T] = unsafe {
std::slice::from_raw_parts_mut(self.begin, self.len)
};
let result = slice.split_at_mut(self.index);
self.index += 1;
Some(result)
}
}
Invoked on [1, 2, 3] it will return (&[], &[1, 2, 3]) then (&[1], &[2, 3]), ... until (&[1, 2, 3], &[]). In short, it iterates over all the potential partitions of the slice (without shuffling).
Which is safe to use as:
fn main() {
let mut data: Vec<u8> = (1..100).collect();
for (head, tail) in WindowIterMut::new(&mut data) {
if let Some(element) = head.last_mut() {
if *element % 2 == 0 {
if let Some(n3) = tail.iter().filter(|i| *i % 3 == 0).next() {
*element += *n3;
}
}
}
}
println!("{:?}", data);
}
Unfortunately it can also be used as:
fn main() {
let mut data: Vec<u8> = (1..100).collect();
let mut it = WindowIterMut::new(&mut data);
let first_0 = { it.next(); &mut it.next().unwrap().0[0] };
let second_0 = &mut it.next().unwrap().0[0];
println!("{:?} {:?}", first_0 as *const _, second_0 as *const _);
}
which when run print: 0x7f73a8435000 0x7f73a8435000, show-casing that both mutable references alias the same element.
Since we cannot get rid of aliasing, we need to get rid of mutability; or at least defer to interior mutability (Cell here since u8 is Copy).
Fortunately, Cell has no runtime cost, but it does cost a bit in ergonomics (all those .get() and .set()).
I take the opportunity to make the iterator slightly more generic too, and rename it since Window is already a used name for a different concept.
struct FingerIter<'a, T>
where T: 'a
{
begin: *const T,
len: usize,
index: usize,
_marker: PhantomData<&'a [T]>,
}
impl<'a, T> FingerIter<'a, T>
where T: 'a
{
pub fn new(slice: &'a [T]) -> FingerIter<'a, T> {
FingerIter {
begin: slice.as_ptr(),
len: slice.len(),
index: 0,
_marker: PhantomData,
}
}
}
impl<'a, T> Iterator for FingerIter<'a, T>
where T: 'a
{
type Item = (&'a [T], &'a T, &'a [T]);
fn next(&mut self) -> Option<Self::Item> {
if self.index >= self.len { return None; }
let slice: &'a [T] = unsafe {
std::slice::from_raw_parts(self.begin, self.len)
};
self.index += 1;
let result = slice.split_at(self.index);
Some((&result.0[0..self.index-1], result.0.last().unwrap(), result.1))
}
}
We use it as a building brick:
fn main() {
let data: Vec<Cell<u8>> = (1..100).map(|i| Cell::new(i)).collect();
for (_, element, tail) in FingerIter::new(&data) {
if element.get() % 2 == 0 {
if let Some(n3) = tail.iter().filter(|i| i.get() % 3 == 0).next() {
element.set(element.get() + n3.get());
}
}
}
let data: Vec<u8> = data.iter().map(|cell| cell.get()).collect();
println!("{:?}", data);
}
On the playpen this prints: [1, 5, 3, 10, 5, 15, 7, 17, 9, 22, ...], which seems correct.

Lifetime for Iterator field

In learning this new fascinating language I wrote this code which outputs 0 through 10 multiplied by 3:
pub struct Multiplier {
factor : int,
current : int
}
impl Multiplier {
pub fn new(factor : int) -> Multiplier {
Multiplier {
factor: factor,
current: 0
}
}
}
impl Iterator<int> for Multiplier {
fn next(&mut self) -> Option<int> {
if self.current > 10 {
None
}
else {
let current = self.current;
self.current += 1;
Some(current * self.factor)
}
}
}
struct Holder {
x : Multiplier
}
impl Holder {
pub fn new(factor : int) -> Holder {
Holder {
x : Multiplier::new(factor)
}
}
fn get_iterator(&self) -> Multiplier {
self.x
}
}
fn main() {
let mut three_multiplier = Holder::new(3).get_iterator();
for item in three_multiplier {
println!("{}", item);
}
}
If I change Holder from this
struct Holder {
x : Multiplier
}
to this:
struct Holder {
x : Iterator<int>
}
I get a compilation warning:
<anon>:27:9: 27:22 error: explicit lifetime bound required
<anon>:27 x : Iterator<int>
^~~~~~~~~~~~~
Can anyone explain why changing the field type requires an explicit lifetime? I know how to mark the lifetimes but I'm not sure why the compiler wants me to do this.
You can add a lifetime bound this way:
struct Holder<'a> {
x: Iterator<int>+'a
}
Note however that this way, the Holder struct is unsized, because it contains a trait object, which is unsized. This severely limits what you can do with the type: for example, you can not return a Holder directly.
You can fix this by making Holder accept a type parameter:
struct Holder<T> where T: Iterator<int> {
x : T
}
Let's change get_iterator to use the type parameter:
impl<T> Holder<T> where T: Iterator<int>+Copy {
fn get_iterator(&self) -> T {
self.x
}
}
Note: I added the Copy bound here because get_iterator currently returns a copy. You could avoid the bound by making get_iterator return a &T instead.
As for new, you'll have to completely redesign it. If we keep it as is, the compiler gives error if we call it as Holder::new because Holder now has a type parameter, and the compiler cannot infer a type because new doesn't use any. To solve this, we can make new generic by using a trait to provide the constructor:
trait FactorCtor {
fn new(factor: int) -> Self;
}
And then changing new to use that trait:
impl<T> Holder<T> where T: Iterator<int>+FactorCtor {
pub fn new(factor : int) -> Holder<T> {
Holder {
x : FactorCtor::new(factor)
}
}
}
Because we have only one implementation of FactorCtor in this program, the compiler manages to infer T when calling Holder::new. If we add another implementation, e.g. Adder:
pub struct Adder {
factor : int,
current : int
}
impl FactorCtor for Adder {
fn new(factor: int) -> Adder {
Adder {
factor: factor,
current: 0
}
}
}
impl Iterator<int> for Adder {
fn next(&mut self) -> Option<int> {
if self.current > 10 {
None
}
else {
let current = self.current;
self.current += 1;
Some(current + self.factor)
}
}
}
Then we get a compiler error:
<anon>:72:9: 72:29 error: unable to infer enough type information about `_`; type annotations required
<anon>:72 let mut three_multiplier = Holder::new(3).get_iterator();
^~~~~~~~~~~~~~~~~~~~
We can fix this by specifying T explicitly:
fn main() {
let mut three_multiplier = Holder::<Multiplier>::new(3).get_iterator();
for item in three_multiplier {
println!("{}", item);
}
}