Explain this struct implementation in Rust - struct

// `Inches`, a tuple struct that can be printed
#[derive(Debug)]
struct Inches(i32);
impl Inches {
fn to_centimeters(&self) -> Centimeters {
let &Inches(inches) = self;
Centimeters(inches as f64 * 2.54)
}
}
I understand that the function signature takes a reference of the Inches struct as a parameter, what does the first line in the function definition mean?

In the let a = b syntax, a doesn't just have to be an indentifier for a new variable, it can also be a pattern much like in match arms:
let a = 0;
let (a, c) = (0, 1);
let &a = &0;
let Inches(a) = Inches(0);
So what you see here is self being matched as a &Inches and pulling out the inner value into a new variable called "inches".
This statement is probably more universally readable as:
let inches = self.0;

Related

Recursive closure inside a function [duplicate]

This is a very simple example, but how would I do something similar to:
let fact = |x: u32| {
match x {
0 => 1,
_ => x * fact(x - 1),
}
};
I know that this specific example can be easily done with iteration, but I'm wondering if it's possible to make a recursive function in Rust for more complicated things (such as traversing trees) or if I'm required to use my own stack instead.
There are a few ways to do this.
You can put closures into a struct and pass this struct to the closure. You can even define structs inline in a function:
fn main() {
struct Fact<'s> { f: &'s dyn Fn(&Fact, u32) -> u32 }
let fact = Fact {
f: &|fact, x| if x == 0 {1} else {x * (fact.f)(fact, x - 1)}
};
println!("{}", (fact.f)(&fact, 5));
}
This gets around the problem of having an infinite type (a function that takes itself as an argument) and the problem that fact isn't yet defined inside the closure itself when one writes let fact = |x| {...} and so one can't refer to it there.
Another option is to just write a recursive function as a fn item, which can also be defined inline in a function:
fn main() {
fn fact(x: u32) -> u32 { if x == 0 {1} else {x * fact(x - 1)} }
println!("{}", fact(5));
}
This works fine if you don't need to capture anything from the environment.
One more option is to use the fn item solution but explicitly pass the args/environment you want.
fn main() {
struct FactEnv { base_case: u32 }
fn fact(env: &FactEnv, x: u32) -> u32 {
if x == 0 {env.base_case} else {x * fact(env, x - 1)}
}
let env = FactEnv { base_case: 1 };
println!("{}", fact(&env, 5));
}
All of these work with Rust 1.17 and have probably worked since version 0.6. The fn's defined inside fns are no different to those defined at the top level, except they are only accessible within the fn they are defined inside.
As of Rust 1.62 (July 2022), there's still no direct way to recurse in a closure. As the other answers have pointed out, you need at least a bit of indirection, like passing the closure to itself as an argument, or moving it into a cell after creating it. These things can work, but in my opinion they're kind of gross, and they're definitely hard for Rust beginners to follow. If you want to use recursion but you have to have a closure, for example because you need something that implements FnOnce() to use with thread::spawn, then I think the cleanest approach is to use a regular fn function for the recursive part and to wrap it in a non-recursive closure that captures the environment. Here's an example:
let x = 5;
let fact = || {
fn helper(arg: u64) -> u64 {
match arg {
0 => 1,
_ => arg * helper(arg - 1),
}
}
helper(x)
};
assert_eq!(120, fact());
Here's a really ugly and verbose solution I came up with:
use std::{
cell::RefCell,
rc::{Rc, Weak},
};
fn main() {
let weak_holder: Rc<RefCell<Weak<dyn Fn(u32) -> u32>>> =
Rc::new(RefCell::new(Weak::<fn(u32) -> u32>::new()));
let weak_holder2 = weak_holder.clone();
let fact: Rc<dyn Fn(u32) -> u32> = Rc::new(move |x| {
let fact = weak_holder2.borrow().upgrade().unwrap();
if x == 0 {
1
} else {
x * fact(x - 1)
}
});
weak_holder.replace(Rc::downgrade(&fact));
println!("{}", fact(5)); // prints "120"
println!("{}", fact(6)); // prints "720"
}
The advantages of this are that you call the function with the expected signature (no extra arguments needed), it's a closure that can capture variables (by move), it doesn't require defining any new structs, and the closure can be returned from the function or otherwise stored in a place that outlives the scope where it was created (as an Rc<Fn...>) and it still works.
Closure is just a struct with additional contexts. Therefore, you can do this to achieve recursion (suppose you want to do factorial with recursive mutable sum):
#[derive(Default)]
struct Fact {
ans: i32,
}
impl Fact {
fn call(&mut self, n: i32) -> i32 {
if n == 0 {
self.ans = 1;
return 1;
}
self.call(n - 1);
self.ans *= n;
self.ans
}
}
To use this struct, just:
let mut fact = Fact::default();
let ans = fact.call(5);

What's the difference between One::one() vs 1

What is the difference between One::one() and just the number 1? Is there any difference?
One::one() is intended to be used in generic code where we do not know what is the exact type of the numerical value.
It could be 1_i32, 1.0, 1_u8... depending on the exact type the One trait is bound to.
Thanks to the useful comments below, here is a minimal example to try to illustrate better (although it's late).
Trying to initialise some variables with 1 works if they are considered as integers (a and c here).
On the other hand, this does not work for a real (b here); 1.0 must be used instead.
When it comes to our own non-primtive type (Thing here), the One trait helps providing a value considered as 1 (note that the Mul trait must be implemented on this type too).
The One trait becomes really useful in a generic function in which the exact type is not already known when we need the 1 value (like mul_one() here).
use num_traits::One;
use std::ops::Mul;
#[derive(Debug)]
struct Thing {
member: String,
}
// Mul<Self, Output = Self> is required for One
impl Mul for Thing {
type Output = Self;
fn mul(
self,
rhs: Self,
) -> Self {
Self {
member: self.member + "×" + &rhs.member,
}
}
}
impl One for Thing {
fn one() -> Self {
Self {
member: "one".to_owned(),
}
}
}
fn mul_one<T: One>(arg: T) -> T {
// arg * 1 // error: expected type parameter `T`, found integer
arg * T::one()
}
fn main() {
let a: i32 = 1;
// let b: f64 = 1; // error: expected `f64`, found integer
let b: f64 = 1.0;
let c: u8 = 1;
let d = Thing::one();
println!("{:?} {:?} {:?} {:?}", a, b, c, d);
let e = mul_one(a);
let f = mul_one(b);
let g = mul_one(c);
let h = mul_one(d);
println!("{:?} {:?} {:?} {:?}", e, f, g, h);
}
/*
1 1.0 1 Thing { member: "one" }
1 1.0 1 Thing { member: "one×one" }
*/

Mutability in fields for structs in Rust

I'm still new with Rust but I have doubts about how mutability works for fields in structs. Specifically how we can modify fields that originally were immutable. For example:
struct Point {
x: isize,
y: isize,
}
impl Point {
fn new(x: isize, y: isize) -> Self {
Self { x, y }
}
fn set_x(&mut self, new_x: isize) {
self.x = new_x;
}
}
struct Line {
p: Point,
q: Point,
}
impl Line {
fn new(p: Point, q: Point) -> Self {
Self { p, q }
}
fn set_x_in_p(&mut self, new_x: isize) {
self.p.set_x(new_x);
}
}
fn main() {
// Both x and y are immutable
let p = Point::new(0, 0);
let q = Point::new(1, 1);
// Line IS mutable
let mut line = Line::new(p, q);
// Modifying point p (originally immutable) with a new x
line.set_x_in_p(999);
}
Instead with references we cannot
let x = 3;
let y = &mut x; // does not work because x originally is immutable
So, how does it work? Thanks.
In your example, p and q are indeed immutable, but then you move them into a Line instance with the constructor, since they're passed by value and don't implement Copy to enable implicit copying. This means that the original bindings (p and q) are no longer valid (the compiler will prevent you from using them) and the values are instead accessible only via the mutable line binding, which allows mutating its members. Essentially, it's not the values that are mutable, but rather their bindings. For example, the following code can be used to re-bind a value to change its mutability:
let x = String::from("hello world"); // using String as an example of a non-Copy type
let mut x = x; // this shadows the previous binding with a mutable one of the same name
x.make_ascii_uppercase(); // we can now mutate the string
let x = x; // shadow the mutable binding with an immutable one
println!("Result: {}", x);
This example works because we have direct control over the value, and can move/bind it as desired. Introducing references would limit what could be done - for example, the following examples wouldn't work:
let x = String::from("hello world");
let x_ref = &x; // create an immutable reference to x
let mut x_mut = x; // error - we can't move x while it's borrowed
let x_mut_ref = &mut x; // error - we can't create a mutable reference while any other references exist
I'd recommend reading the ownership and moves page of Rust by example, which explains it pretty well.
When you are declaring x, you are specifying it as immutable with the let instead of let mut. When you then declare y and initialize it as &mut x you are attempting to borrow x. In Rust, the one thing you can never do is simultaneously have shared ownership AND mutability.
Check out what Niko Matsakis has to say about ownership.

Returning modified array from for loop without type mismatch

In pseudo-code, I'm trying to do the following:
my_array = [[1,2,3,4],[5,6,7,8]]
my_array = array_modify_fn(my_array)
fn array_modify_fn(array) {
for i in array {
array[i] = some_operation
}
}
Having read this question about the type mismatch this kind of loop/function would cause in Rust, I'm still confused as to how to actually implement what I want to implement here, but in Rust.
Am I just going about the problem in the wrong way? (For Rust at least; this is how I would do it in Python.)
My Rust at the moment looks like this:
let mut life_array = [[false; SIZE]; SIZE];
life_array = random_init(&mut life_array); // in main function
fn random_init(arr: &mut [[bool; SIZE]; SIZE]) -> [[bool; SIZE]; SIZE] {
for i in 0 .. (SIZE*SIZE) {
arr[i/SIZE][i%SIZE] = rand::random()
}
}
and this returns the type mismatch: expected type '[[bool; SIZE]; SIZE]' found type '()'
You've defined random_init with a return type, yet your function doesn't return anything (strictly speaking, it returns ()). Since you're mutating the array in-place, your function doesn't have to return anything, so you should just omit the return type.
const SIZE: usize = 4;
extern crate rand;
fn main() {
let mut life_array = [[false; SIZE]; SIZE];
random_init(&mut life_array);
}
fn random_init(arr: &mut [[bool; SIZE]; SIZE]) {
for i in 0..(SIZE * SIZE) {
arr[i / SIZE][i % SIZE] = rand::random()
}
}

Is it necessary to cast to float to access basic math functions in Rust?

fn main() {
let a = 1i32;
let b = 2i32;
let smallest = (a as f64).min((b as f64)) as i32;
println!("{}", smallest);
}
Is all the casting to and from floats really necessary?
The function you're looking for is ::std::cmp::min, which works on any type that implements Ord:
fn main() {
let a = 1i32;
let b = 2i32;
let smallest = ::std::cmp::min(a, b);
println!("{}", smallest);
}
You were using the min method from f64 (an equivalent exists for f32).
No. As a quick search of the API reference reveals, you can just use std::cmp::min:
use std::cmp::min;
fn main() {
let a = 1i32;
let b = 2i32;
let smallest = min(a, b);
println!("{}", smallest);
}
min being declared specially on f32 and f64 is because floating point types do not implement Ord. Due to the presence of NaN, they only have partial ordering (PartialOrd) whilst std::cmp::min requires a total ordering (Ord).

Resources