126 lines
3.3 KiB
Rust
126 lines
3.3 KiB
Rust
fn copyable() {
|
|
// All numeric primitives, signed and unsigned are copyable
|
|
let a: i64 = 10;
|
|
let b = a;
|
|
let c: f32 = 0.1;
|
|
let d = c;
|
|
println!("a and c are not moved: {} {}", a, c);
|
|
|
|
// Bools too
|
|
let e = true;
|
|
let f = e;
|
|
println!("Bools are copyable too: {}", e);
|
|
|
|
// Char's and string slices are copyable too, BUT NOT Strings
|
|
let g: char = 'g';
|
|
let h = g;
|
|
let i = "string slices are copyable";
|
|
let j = i;
|
|
println!("chars are copyable: {} aaaand {}", g, i);
|
|
|
|
// Arrays and array slices too
|
|
let k = [1, 2, 3];
|
|
let l = k;
|
|
// Get a slice of the first entry in the k array
|
|
let m = &k[0..1];
|
|
let n = m;
|
|
println!("Arrays and array slices are copyable: {:?} {:?}", k, m);
|
|
|
|
// Tuples too
|
|
let o = (1, "str");
|
|
let p = o;
|
|
println!("Tuples are copyable {:?}", o);
|
|
|
|
// That was the types that are copyable by default
|
|
// We can also implement Copy on our own types as long
|
|
// as they hold copyable types themselves
|
|
struct Point {
|
|
x: i32,
|
|
y: i32,
|
|
}
|
|
impl Copy for Point {}
|
|
impl Clone for Point { fn clone(&self) -> Point { *self } }
|
|
let q = Point { x: 1, y: 10 };
|
|
let r = q;
|
|
println!("We made a copyable struct! {}/{}", q.x, q.y);
|
|
|
|
// Phew! that was some black magic. Copy and Clone are `traits` that are built into the language
|
|
// Traits are basically interfaces that you can implement on your types
|
|
// You can create them yourselves too, which we'll get to in a future post
|
|
// There is an easier way to make a type copyable though:
|
|
#[derive(Copy, Clone, Debug)]
|
|
struct Point3D {
|
|
x: i32,
|
|
y: i32,
|
|
z: i32,
|
|
}
|
|
let s = Point3D { x: 1, y: -20, z: 30 };
|
|
let t = s;
|
|
println!("Point3D is now copyable, and the Debug trait let's us print it easily {:?}", s);
|
|
}
|
|
|
|
fn borrowing() {
|
|
|
|
#[derive(Clone, Debug)]
|
|
struct Point {
|
|
x: i32,
|
|
y: i32,
|
|
}
|
|
|
|
let a = Point {
|
|
x: 0,
|
|
y: 0,
|
|
};
|
|
|
|
// As discussed this would cause a `moved value` error
|
|
// let b = a;
|
|
// let c = a;
|
|
|
|
// Borrowing is fine an unlimited amount of times though
|
|
let b = &a;
|
|
let c = &a;
|
|
|
|
// But only for as long as the reference lives
|
|
// Rust is block scoped, basically any time you see {} it's a block
|
|
{
|
|
let d = Point { x: 0, y: 0 };
|
|
|
|
// This is totally fine
|
|
let e = &d;
|
|
|
|
// But here, at the end of this block, d goes out of scope
|
|
}
|
|
|
|
// So this would fail
|
|
// let f = &d;
|
|
|
|
// You can also borrow a value mutably, but then the borrower has
|
|
// exclusive rights to mutate the value until it goes out of scope
|
|
let mut f = Point { x: 0, y: 0 };
|
|
let g = &mut f;
|
|
|
|
// This would fail
|
|
// let h = &mut f;
|
|
|
|
// Even the owner can't mutate itself without causing an error
|
|
// f.x = 1;
|
|
|
|
// This means that mutable borrows are mostly practical when passing something to a function
|
|
|
|
fn pointifier(point: &mut Point, multiply_by: i32) {
|
|
point.x *= multiply_by;
|
|
point.y *= multiply_by;
|
|
}
|
|
|
|
let mut h = Point { x: 1, y: 2 };
|
|
pointifier(&mut h, 20);
|
|
|
|
// once the pointifier function has finished, the borrow ends, and h is mutable again
|
|
h.x -= 1;
|
|
println!("Point {:?}", h);
|
|
}
|
|
|
|
fn main() {
|
|
copyable();
|
|
borrowing();
|
|
} |