How to create Struct methods and use them in Rust - rust

I am relatively new to the Rust Programming Language. And I was learning about Struct and Enums. I created a program to store the day of the week and see if it is a weekend or not as a test program. The code goes as follows:
#[derive(Debug)]
enum DaysOfTheWeekNames {
Friday,
Saturday,
Sunday,
}
#[derive(Debug)]
struct Weekday {
day: DaysOfTheWeekNames,
weekend: bool,
}
impl Weekday {
fn isWeekend(day: DaysOfTheWeekNames) -> bool {
match day {
DaysOfTheWeekNames::Saturday => false,
DaysOfTheWeekNames::Sunday => false,
other => true,
}
}
fn new_day(day: DaysOfTheWeekNames) -> Self {
Self { day, weekend: Weekday::isWeekend(day) }
}
}
fn main() {
let today = Weekday::new_day(DaysOfTheWeekNames::Saturday);
println!("Today: {:#?}", today);
}
So my objective here is to create a struct called Weekday, and want to initialize it using the method called new_day() to which I only pass in the name of the weekday. This function should call the isWeekend() method to find if it is a weekend or not.
But the above code is throwing an error as expected, as the ownership of the variable name is moved to the isWeekend function and not transferred back. So what is the ideal way to write such a use case, and how should we resolve this?
The error, I see is the following:
error[E0382]: use of moved value: `day`
--> src/main.rs:115:50
|
114 | fn new(day: DaysOfTheWeek) -> Self {
| --- move occurs because `day` has type `DaysOfTheWeek`, which does not implement the `Copy` trait
115 | Self { day, weekend: Weekday::is_weekend(day) }
| --- value moved here ^^^ value used here after move

Resolved this.
Explanation: As isWeekend is a struct method, we shouldn't pass struct fields of an instance, which we are doing above (i.e. day). To resolve this, we have to copy or clone the day param, and then pass it to the isWeekend() function.
Code:
#[derive(Debug)]
#[derive(Clone, Copy)]
enum DaysOfTheWeekNames {
Friday,
Saturday,
Sunday,
}
#[derive(Debug)]
struct Weekday {
day: DaysOfTheWeekNames,
weekend: bool,
}
impl Weekday {
fn is_weekend(day: DaysOfTheWeekNames) -> bool {
match day {
DaysOfTheWeekNames::Saturday => true,
DaysOfTheWeekNames::Sunday => true,
_ => false,
}
}
fn new_day(day: DaysOfTheWeekNames) -> Self {
Self { day, weekend: Weekday::is_weekend(day.clone()) }
}
}
fn main() {
let today = Weekday::new_day(DaysOfTheWeekNames::Saturday);
println!("Today: {:#?}", today);
}

Related

How can I chain functions that take the previous result and that fulfill a strict order?

Example:
let response = add_customer(InputCustomer)
.validate()?
.generate_code()
.create(DB::create(pool_conextion))?;
I tried using various structures, but I don't know if it is the best way to do it:
struct InputCustomer {}
fn add_customer(i: InputCustomer) -> Validate {
Validate {
result: InputCustomer {},
}
}
struct Validate {
result: InputCustomer,
}
impl Validate {
fn do_validate() -> GenCode {
// valdiate struct customer
GenCode {
result: InputCustomer {},
}
}
}
struct GenCode {
result: InputCustomer,
}
impl GenCode {
fn generate_code() -> Create {
// generate customer code
Create { result: true }
}
}
struct Create {
result: bool,
}
You can implement all the functions on a single struct using phantom type parameters. The Customer struct holds some state:
pub struct Customer<State> {
state: PhantomData<State>,
}
We can create the possible states that a Customer can be in:
pub struct CustomerStateNew;
pub struct CustomerStateValidated;
pub struct CustomerStateWithCode;
When you create a Customer, it's state is CustomerStateNew:
pub fn add_customer() -> Customer<CustomerStateNew> {
Customer { state: PhantomData }
}
To validate a Customer it must be in the CustomerStateNew state:
impl Customer<CustomerStateNew> {
pub fn validate(&self) -> Customer<CustomerStateValidated> {
Customer { state: PhantomData }
}
}
The Customer must be validated (CustomerStateValidated) to generate a code:
impl Customer<CustomerStateValidated> {
pub fn generate_code(&self) -> Customer<CustomerStateWithCode> {
Customer { state: PhantomData }
}
}
And it must have a generated code (CustomerStateWithCode) to be created. create consumes self, so the customer cannot be used after it is created (you might not want this behavior, but I included it here for completeness):
impl Customer<CustomerStateWithCode> {
pub fn create(self) -> Result<(), ()> {
Ok(())
}
}
Now we can chain together the methods to create the user:
let result = add_customer().validate().generate_code().create()?;
However, it we try to create the Customer before it is validated, the code will not compile:
let result = add_customer().create();
// error[E0599]: no method named `create` found for struct `Customer<CustomerStateNew>`
// --> src/main.rs:36:20
// 36 | add_customer().create();
// | ^^^^^^ method not found in `Customer<CustomerStateNew>`
Also, no one else can create a Customer with an arbitrary state, because the state field is private:
mod somewhere_else {
fn bla() {
let customer: Customer<CustomerStateWithCode> = Customer { state: PhantomData };
customer.create();
}
}
// error[E0451]: field `state` of struct `Customer` is private
// --> src/main.rs:41:64
// |
// 41 | let customer: Customer<CustomerStateWithCode> = Customer { state: PhantomData };
// |
If you want to store data specific to each state, you can store that actual State inside the Customer instead of PhantomData. Now however, the state is more than just compile time safety and will be stored at runtime:
pub struct CustomerStateWithCode(pub usize);
pub struct Customer<State> {
state: State,
}
impl Customer<CustomerStateValidated> {
pub fn generate_code(&self) -> Customer<CustomerStateWithCode> {
Customer { state: CustomerStateWithCode(1234) }
}
}
We have created a simple state machine using phantom types. This is also knows as the type state pattern. Note that the states will be compiled away to nothing, so there is no runtime cost, only compile time safety!
Playground link

Create an iterator and put it into a new struct without bothering the borrow-checker [duplicate]

This question already has answers here:
Is there any way to return a reference to a variable created in a function?
(5 answers)
Closed 3 years ago.
I am trying to create a lexical analyzer which uses itertools::PutBack to make an iterator over the characters in a String. I intend to store the pushback iterator in a struct and delegate methods to it so that I can categorize the characters by an enum, which will then be passed to a state machine at the core of the lexical analyzer (not yet written).
The borrow-checker is not happy with me. Method ParserEventIterator::new near the bottom of the listing causes the error. How do I define the lifetimes or borrowing so that I can get this to compile? Or what Rustic data structure design should I use in its stead?
Ultimately, I would like this to implement the appropriate traits to become a proper iterator. (Newbie to Rust. Prior to this, I have programmed in 28 languages, but this one has me stumped.)
Here is a code sample:
extern crate itertools;
use itertools::put_back;
use std::fmt::Display;
use std::fmt::Formatter;
use std::fmt::Result;
pub enum ParserEvent {
Letter(char),
Digit(char),
Other(char),
}
impl ParserEvent {
fn new(c: char) -> ParserEvent {
match c {
'a'...'z' | 'A'...'Z' => ParserEvent::Letter(c),
'0'...'9' => ParserEvent::Digit(c),
_ => ParserEvent::Other(c),
}
}
}
impl Display for ParserEvent {
fn fmt(&self, f: &mut Formatter) -> Result {
let mut _ctos = |c: char| write!(f, "{}", c.to_string());
match self {
ParserEvent::Letter(letter) => _ctos(*letter),
ParserEvent::Digit(digit) => _ctos(*digit),
ParserEvent::Other(o) => _ctos(*o),
}
}
}
// ParserEventIterator
// Elements ('e) must have lifetime longer than the iterator ('i).
pub struct ParserEventIterator<'i, 'e: 'i> {
char_iter: &'i mut itertools::PutBack<std::str::Chars<'e>>,
}
impl<'i, 'e: 'i> ParserEventIterator<'i, 'e> {
fn new(s: &'e std::string::String) -> ParserEventIterator<'i, 'e> {
// THIS NEXT LINE IS THE LINE WITH THE PROBLEM!!!
ParserEventIterator {
char_iter: &mut put_back(s.chars()),
}
}
fn put_back(&mut self, e: ParserEvent) -> () {
if let Some(c) = e.to_string().chars().next() {
self.char_iter.put_back(c);
}
}
}
impl<'i, 'e: 'i> Iterator for ParserEventIterator<'i, 'e> {
type Item = ParserEvent;
fn next(&mut self) -> Option<ParserEvent> {
match self.char_iter.next() {
Some(c) => Some(ParserEvent::new(c)),
None => None,
}
}
}
fn main() {
let mut _i = ParserEventIterator::new(&String::from("Hello World"));
}
On the Rust Playground
error[E0515]: cannot return value referencing temporary value
--> src/main.rs:43:9
|
43 | / ParserEventIterator {
44 | | char_iter: &mut put_back(s.chars()),
| | ------------------- temporary value created here
45 | | }
| |_________^ returns a value referencing data owned by the current function
Well, the compiler is almost telling you the solution by reflecting to the obvious problem: you can't have a borrow which doesn't live long enough, i.e. the borrow would point to a nonexistent location after the stack memory of the function has been destroyed.
This would happen because the borrow is referencing an object (in this case an itertools::struct::PutBack instance) that has been newly created within the function body. This instance gets destroyed at the end of the function along with all the references to it. So the compiler is preventing you to have a so called dangling pointer.
Thus, instead of borrowing you should move the PutBack instance into your struct:
// ...
pub struct ParserEventIterator<'e> {
char_iter: itertools::PutBack<std::str::Chars<'e>>
}
impl<'e> ParserEventIterator<'e> {
fn new(s: &'e std::string::String) -> ParserEventIterator<'e> {
ParserEventIterator { char_iter: put_back(s.chars()) }
}
// ...
}

How do I correctly implement std::iter::Step in Rust 1.25 nightly?

I am trying to implement a struct to represent a date, which can be used with range syntax (for d in start..end { }). I know there are already crates out there that handle dates, but I am doing this as an exercise.
Here is the struct:
type DayOfMonth = u8;
type Month = u8;
type Year = u16;
#[derive(PartialEq, Eq, Clone)]
pub struct Date {
pub year: Year,
pub month: Month,
pub day: DayOfMonth
}
Here is how I would like to use it:
fn print_dates() {
let start = Date { year: 1999, month: 1, day: 1 };
let end = Date { year: 1999, month: 12, day: 31 };
for d in start..end {
println!("{}-{}-{}", d.year, d.month, d.day);
}
}
I originally tried implementing the Iterator trait, but then when I tried to use range syntax, I got a compiler error saying I needed to implement Step instead.
The documentation shows this signature for the Step trait.
pub trait Step: PartialOrd<Self> + Clone {
fn steps_between(start: &Self, end: &Self) -> Option<usize>;
fn replace_one(&mut self) -> Self;
fn replace_zero(&mut self) -> Self;
fn add_one(&self) -> Self;
fn sub_one(&self) -> Self;
fn add_usize(&self, n: usize) -> Option<Self>;
}
I've already implemented Ord and PartialOrd:
impl Ord for Date {
fn cmp(&self, other: &Self) -> Ordering {
match self.year.cmp(&other.year) {
Ordering::Equal =>
match self.month.cmp(&other.month) {
Ordering::Equal =>
self.day.cmp(&other.day),
ord => ord
},
ord => ord
}
}
}
impl PartialOrd for Date {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
I am implementing Clone automatically with #[derive(Clone)].
I started implementing Step, but there are some methods that I cannot figure out what to do with. Here is what I have so far:
impl Step for Date {
fn steps_between(start: &self, end: &self) -> Option<usize> {
//is_valid_date checks that the month is not > 12 and other rules like that
if is_valid_date(start) && is_valid_date(end) {
//get_epoch_day_number gets the number of days since 1900-01-01
let diff = get_epoch_day_number(end) - get_epoch_day_number(start);
Some(diff)
}
else { None }
}
fn add_one(&self) -> Self {
//Try the next day
let mut next = Date {
year: self.year,
month: self.month,
day: self.day + 1
};
//If not valid, try the 1st of the next month
if !is_valid_date(&next) {
next = Date {
year: self.year,
month: self.month + 1,
day: 1
};
}
//If not valid, try the 1st of the next year
if !is_valid_date(&next) {
next = Date {
year: self.year + 1,
month: 1,
day: 1
};
}
next
}
fn sub_one(&self) -> Self {
//Try the prev day
let mut prev = Date {
year: self.year,
month: self.month,
day: self.day - 1
};
//If not valid, try the last of the prev month
if !is_valid_date(&prev) {
let m = self.month - 1;
prev = Date {
year: self.year,
month: m,
day: get_month_length(self.year, m)
};
}
//If not valid, try the last of the prev year
if !is_valid_date(&prev) {
prev = Date {
year: self.year - 1,
month: 12,
day: 31
};
}
prev
}
fn add_usize(&self, n: usize) -> Self {
//This is really inefficient, but that's not important
let mut result = self;
for i in 1..n+1 {
result = result.add_one();
}
result
}
fn replace_one(&mut self) -> Self {
// ?
}
fn replace_zero(&mut self) -> Self {
// ?
}
}
I am really stumped on what replace_one and replace_zero are supposed to do. The documentation says:
Replaces this step with 1, returning itself. and Replaces this step with 0, returning itself.
Does my struct need to have zero and one identity values just to be used in a range? Shouldn't add_one be enough?
The wording used by the documentation is also a little unclear. If we replace x with 1 and return "itself", is "it" x or 1?
I just looked at Rust's code where those methods are used. The only uses in whole of rustc's repository are to implement RangeInclusive operations. An empty RangeInclusive is represented as a range from 1 to 0, so the next, next_back and nth methods need to be able to get those somehow, and that's what replace_one and replace_zero are for.
I would suggest opening an issue on rustc's GitHub to make the documentation better, and possibly change the name of these methods.

Use of moved value when pattern matching an enum with multiple values after downcasting

I can use pattern matching on an enum that has one String parameter:
extern crate robots;
use std::any::Any;
use robots::actors::{Actor, ActorCell};
#[derive(Clone, PartialEq)]
pub enum ExampleMessage {
Msg { param_a: String },
}
pub struct Dummy {}
impl Actor for Dummy {
// Using `Any` is required for actors in RobotS
fn receive(&self, message: Box<Any>, _context: ActorCell) {
if let Ok(message) = Box::<Any>::downcast::<ExampleMessage>(message) {
match *message {
ExampleMessage::Msg { param_a } => println!("got message"),
}
}
}
}
And yet I am unable to perform pattern matching on an enum with 2 parameters:
#[derive(Clone, PartialEq)]
pub enum ExampleMessage {
Msg { param_a: String, param_b: usize },
}
impl Actor for Dummy {
// Using `Any` is required for actors in RobotS
fn receive(&self, message: Box<Any>, _context: ActorCell) {
if let Ok(message) = Box::<Any>::downcast::<ExampleMessage>(message) {
match *message {
ExampleMessage::Msg { param_a, param_b } => println!("got message"),
}
}
}
}
This results in the error:
error[E0382]: use of moved value: `message`
--> src/example.rs:19:48
|
19 | ExampleMessage::Msg { param_a, param_b } => {
| ------- ^^^^^^^ value used here after move
| |
| value moved here
|
= note: move occurs because `message.param_a` has type `std::string::String`, which does not implement the `Copy` trait
I tried pattern matching on the same enum without downcasting before, and this works fine but I am required to downcast.
This just seems like very strange behavior to me and I don't know how to circumvent this error.
I am using Rust 1.19.0-nightly (afa1240e5 2017-04-29)
I tried pattern matching on the same enum without downcasting before, and this works fine
This is a good attempt at reducing the problem. The issue is that you reduced too far. Downcasting a Box<T> to a Foo doesn't return a Foo, it returns a Box<Foo>:
fn downcast<T>(self) -> Result<Box<T>, Box<Any + 'static>>
You can reproduce the problem with:
#[derive(Clone, PartialEq)]
pub enum ExampleMessage {
Msg { param_a: String, param_b: usize },
}
fn receive2(message: Box<ExampleMessage>) {
match *message {
ExampleMessage::Msg { param_a, param_b } => println!("got message"),
}
}
fn main() {}
The good news
This is a limitation of the current implementation of the borrow checker and your original code will work as-is when non-lexical lifetimes are enabled:
#![feature(nll)]
#[derive(Clone, PartialEq)]
pub enum ExampleMessage {
Msg { param_a: String, param_b: usize },
}
fn receive2(message: Box<ExampleMessage>) {
match *message {
ExampleMessage::Msg { param_a, param_b } => println!("got message"),
}
}
fn main() {}
The current reality
Non-lexical lifetimes and the MIR-based borrow checker are not yet stable!
When you match against a dereferenced value, the value is not normally moved. This allows you to do something like:
enum Foo {
One,
Two,
}
fn main() {
let f = &Foo::One;
match *f {
Foo::One => {}
Foo::Two => {}
}
}
In this case, you wish to take ownership of the thing inside the Box1 in order to take ownership of the fields when destructuring it in the match. You can accomplish this by moving the value out of the box before trying to match on it.
The long way to do this is:
fn receive2(message: Box<ExampleMessage>) {
let message = *message;
match message {
ExampleMessage::Msg { param_a, param_b } => println!("got message"),
}
}
But you can also force the move by using curly braces:
fn receive2(message: Box<ExampleMessage>) {
match {*message} {
ExampleMessage::Msg { param_a, param_b } => println!("got message"),
}
}
I don't fully understand why a single field would work; it's certainly inconsistent. My only guess is that the ownership of the Box is moved to the first param, the param is extracted, then the compiler tries to move it again to the next parameter.
1 — Moving the contained element out via * is a special power that only Box supports. For example, if you try to do this with a reference, you get the "cannot move out of borrowed content" error. You cannot implement the Deref trait to do this either; it's a hard-coded ability inside the compiler.

How to prevent a value from being moved?

I'm having a lot of fun trying to solve the robot simulator Exercism exercise, but I'm facing a value moving problem for which I don't seem to be able to come up with an elegant solution:
impl Robot {
pub fn new(x: isize, y: isize, d: Direction) -> Self {
Robot { position: Coordinate { x: x, y: y }, direction: d }
}
pub fn turn_right(mut self) -> Self {
match self.direction {
// ...
};
self
}
pub fn turn_left(mut self) -> Self {
match self.direction {
// ...
};
self
}
pub fn advance(mut self) -> Self {
match self.direction {
// ...
};
self
}
pub fn instructions(self, instructions: &str) -> Self {
for instruction in instructions.chars() {
match instruction {
'A' => { self.advance(); },
'R' => { self.turn_right(); },
'L' => { self.turn_left(); },
_ => {
println!("{} is not a valid instruction", instruction);
},
};
}
self
}
I get this error :
enter code hereerror[E0382]: use of moved value: `self`
--> src/lib.rs:60:26
|
60 | 'A' => { self.advance(); },
| ^^^^ value moved here in previous iteration of loop
|
= note: move occurs because `self` has type `Robot`, which does not implement the `Copy` trait
error[E0382]: use of moved value: `self`
--> src/lib.rs:61:26
|
60 | 'A' => { self.advance(); },
| ---- value moved here
61 | 'R' => { self.turn_right(); },
| ^^^^ value used here after move
|
= note: move occurs because `self` has type `Robot`, which does not implement the `Copy` trait
I think I get the error because advance() returns self, but I don't understand why the value is still moved as it's used inside a block. Do I really have to implement Copy or am I missing a lifetime use case?
I think I get the error because advance() returns self ?
No, you're getting that error because advance consumes self (and your other methods do, too).
The idiomatic solution to your problem is almost certainly to have your methods take a mutable reference (&mut) to self instead of taking self by value. E.g. the signature pub fn turn_right(mut self) -> Self would become pub fn turn_right(&mut self) (note that the latter does not return anything). You can manipulate the robot's state through the reference, and your instructions function should work fine.
If for some reason you want to continue to have the methods take self by value, you could rewrite instructions as follows:
pub fn instructions(self, instructions: &str) -> Self {
let mut robot = self;
for instruction in instructions.chars() {
robot = match instruction {
'A' => { robot.advance() },
'R' => { robot.turn_right() },
'L' => { robot.turn_left() },
_ => {
println!("{} is not a valid instruction", instruction);
robot
},
};
}
robot
}
I.e. continue passing the robot's state by value, but make sure that the new state is bound to a variable at every loop iteration.
(I've not tried to compile this code, but the principle should be sound.)
Looking at the other users answers, you can actually do it with fold :
pub fn instructions(self, instructions: &str) -> Self {
instructions.chars().fold(self, |robot, c| {
match c {
'L' => robot.turn_left(),
'R' => robot.turn_right(),
'A' => robot.advance(),
_ => panic!("unexpected char")
}
})
}
It seems to keep moving back robot into the scope.

Resources