lecture 02
This commit is contained in:
11 files changed
+300
No files matched your search
@@ -0,0 +1,31 @@
|
|||||||
|
- an object can have only 1 owner
|
||||||
|
- assignment/initialization either copies or moves the source
|
||||||
|
* if the source doesn't implement the Copy trait, it is moved to the
|
||||||
|
destination, i.e., ownership is transferred from the source to the
|
||||||
|
destination
|
||||||
|
* copy/move can also occur
|
||||||
|
- when passing by value into a function
|
||||||
|
- returning by value from a function
|
||||||
|
- when pattern-matching
|
||||||
|
- at any time, an object can have
|
||||||
|
EITHER 1 exclusive/mutable reference (&mut) to it
|
||||||
|
OR any number of shared references (&) to it
|
||||||
|
- we need to be aware of the scope of a reference: it starts from its
|
||||||
|
introduction up to and including the last time it is used (i.e., scope
|
||||||
|
of a reference is not lexical)
|
||||||
|
- if an object has any reference to it, it cannot be written to
|
||||||
|
- if an object has a exclusive reference to it, it cannot be read or written
|
||||||
|
(the object is "frozen")
|
||||||
|
|
||||||
|
Copy trait:
|
||||||
|
- an array is Copy (i.e. implements the Copy trait) if its elements are Copy
|
||||||
|
- a tuple is Copy if its elements are Copy
|
||||||
|
|
||||||
|
Basics:
|
||||||
|
let a = ...;
|
||||||
|
&a (OK), &mut a (NOT OK, a is not declared mut)
|
||||||
|
let mut a = ...;
|
||||||
|
&a, &mut a (BOTH OK, but not at the same time)
|
||||||
|
|
||||||
|
let a = ...; // some type that doesn't implement Copy
|
||||||
|
let b = a; // a is moved to b
|
||||||
Generated
+7
@@ -0,0 +1,7 @@
|
|||||||
|
# This file is automatically @generated by Cargo.
|
||||||
|
# It is not intended for manual editing.
|
||||||
|
version = 4
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lec02"
|
||||||
|
version = "0.1.0"
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
[package]
|
||||||
|
name = "lec02"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2024"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
hello world
|
||||||
|
hi
|
||||||
|
goodbye
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
fn test1() {
|
||||||
|
let x = Some(32);
|
||||||
|
println!("{}", x.unwrap());
|
||||||
|
// let x: Option<i32> = None;
|
||||||
|
// println!("{}", x.unrwap()); // panics
|
||||||
|
|
||||||
|
let n = "123".parse::<i32>();
|
||||||
|
println!("{n:?}")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn sqrt(x: f64) -> Option<f64> {
|
||||||
|
if (x < 0.0) { None } else { Some(f64::sqrt(x)) }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn ln_sqrt(x: f64) -> Option<f64> {
|
||||||
|
/*
|
||||||
|
match sqrt(x) {
|
||||||
|
Some(x) => f64::ln(x),
|
||||||
|
None => None,
|
||||||
|
}
|
||||||
|
|
||||||
|
// OR
|
||||||
|
if let Some(x) = sqrt(x) {
|
||||||
|
Some(f64::ln(x))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
Some(f64::ln(sqrt(x)?))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
test1();
|
||||||
|
}
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
use std::env;
|
||||||
|
use std::fs::File;
|
||||||
|
use std::io::{self, BufRead};
|
||||||
|
|
||||||
|
fn read_lines() {
|
||||||
|
let mut line = String::new();
|
||||||
|
|
||||||
|
while let Ok(n) = io::stdin().read_line(&mut line) {
|
||||||
|
if n == 0 {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
print!("{line}");
|
||||||
|
line.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn lines() -> io::Result<Vec<String>> {
|
||||||
|
io::stdin().lines().collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn lines2() -> Vec<String> {
|
||||||
|
io::stdin().lines().filter_map(|x| x.ok()).collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn file_lines(file: &str) -> io::Result<Vec<String>> {
|
||||||
|
io::BufReader::new(File::open(file)?).lines().collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let args: Vec<_> = env::args().skip(1).collect();
|
||||||
|
println!("{args:?}");
|
||||||
|
|
||||||
|
if args.len() > 0 {
|
||||||
|
println!("{:?}", file_lines(&args[0]));
|
||||||
|
} else {
|
||||||
|
println!("{:?}", lines());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
mod strings;
|
||||||
|
mod structs;
|
||||||
|
mod tuples;
|
||||||
|
mod vectors;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
println!("Hello, world!");
|
||||||
|
|
||||||
|
tuples::run();
|
||||||
|
vectors::run();
|
||||||
|
strings::run();
|
||||||
|
structs::run();
|
||||||
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
pub fn run() {
|
||||||
|
println!("STRINGS");
|
||||||
|
|
||||||
|
let s1 = "hello"; // type &str
|
||||||
|
let s2 = String::from("world"); // type String
|
||||||
|
|
||||||
|
print_str(s1);
|
||||||
|
// print_string(s1); // ERROR
|
||||||
|
// print_string_ref(s1); // ERROR
|
||||||
|
|
||||||
|
print_str(&s2); // also accepts &String (Deref trait)
|
||||||
|
print_string_ref(&s2);
|
||||||
|
print_string(s2); // moves s2
|
||||||
|
|
||||||
|
let s = "नमस्ते";
|
||||||
|
println!("{}", s.len()); // byte count -> 18
|
||||||
|
// println!("{}", s[0]); // can't index string
|
||||||
|
println!("{:?}", &s[0..3]); // may panic if not at char boundary
|
||||||
|
for c in s.chars() {
|
||||||
|
println!("{c}");
|
||||||
|
}
|
||||||
|
|
||||||
|
println!("{}", s.chars().count());
|
||||||
|
println!("{:?}", s.as_bytes());
|
||||||
|
}
|
||||||
|
|
||||||
|
// which version of string function should be used?
|
||||||
|
// CONCLUSION: function that takes &str is most flexible
|
||||||
|
fn print_str(s: &str) {
|
||||||
|
println!("{s}");
|
||||||
|
}
|
||||||
|
|
||||||
|
fn print_string(s: String) {
|
||||||
|
println!("{s}");
|
||||||
|
}
|
||||||
|
|
||||||
|
fn print_string_ref(s: &String) {
|
||||||
|
println!("{s}");
|
||||||
|
}
|
||||||
@@ -0,0 +1,66 @@
|
|||||||
|
use std::fmt;
|
||||||
|
|
||||||
|
#[derive(Debug, Copy, Clone)] // derive the implementatoin of the Debug trait (like an interface)
|
||||||
|
struct Point(f64, f64); // tuple struct
|
||||||
|
|
||||||
|
#[derive(Debug, Copy, Clone)]
|
||||||
|
pub struct Circle {
|
||||||
|
center: Point,
|
||||||
|
radius: f64,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for Point {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
write!(f, "({}, {})", self.0, self.1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Circle {
|
||||||
|
// or you can specify -> Self
|
||||||
|
pub fn new(center: Point, radius: f64) -> Circle {
|
||||||
|
// Or you can specify self instead of Circle {
|
||||||
|
Circle { center, radius } // since names are the same, we dont need key: value pair
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn area(&self) -> f64 {
|
||||||
|
std::f64::consts::PI * self.radius * self.radius
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn scale(&mut self, factor: f64) {
|
||||||
|
self.radius *= factor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for Circle {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
write!(f, "Circle: {} {}", self.center, self.radius)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn run() {
|
||||||
|
println!("STRUCTS");
|
||||||
|
|
||||||
|
let p = Point(1.0, 2.0);
|
||||||
|
println!("{} {}", p.0, p.1);
|
||||||
|
|
||||||
|
let Point(x, y) = p;
|
||||||
|
println!("{x} {y}");
|
||||||
|
|
||||||
|
let c = Circle {
|
||||||
|
center: p,
|
||||||
|
radius: 1.0,
|
||||||
|
};
|
||||||
|
println!("{c:?}");
|
||||||
|
|
||||||
|
let mut c = Circle::new(Point(0.0, 0.0), 1.0);
|
||||||
|
|
||||||
|
println!("{}", c.area()); // area will automatically take reference
|
||||||
|
println!("{}", (&c).area()); // or you can specify manually
|
||||||
|
c.scale(2.0);
|
||||||
|
println!("{c:?}");
|
||||||
|
println!("{}", c.area());
|
||||||
|
|
||||||
|
// after implementing Display trait
|
||||||
|
println!("{c}");
|
||||||
|
let _s = format!("{c}"); // format uses Display trait, to convert to string
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
pub fn run() {
|
||||||
|
println!("TUPLES");
|
||||||
|
|
||||||
|
let t = (1, 3.14);
|
||||||
|
println!("{} {}", t.0, t.1);
|
||||||
|
println!("{t:?}"); // debug print
|
||||||
|
|
||||||
|
let (x, y) = t; // pattern matching
|
||||||
|
println!("{x} {y}");
|
||||||
|
println!("{:?}", swap(&t));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn swap(t: &(i32, f64)) -> (f64, i32) {
|
||||||
|
(t.1, t.0)
|
||||||
|
}
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
pub fn run() {
|
||||||
|
println!("VECTORS");
|
||||||
|
let v = vec![3, 2, 7, 6, 8]; // macro for creating vector with known type
|
||||||
|
println!("{v:?}");
|
||||||
|
|
||||||
|
for i in 0..v.len() {
|
||||||
|
println!("{}", v[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// x has typ &i32
|
||||||
|
// for x in &v {
|
||||||
|
// println!("{x}");
|
||||||
|
// }
|
||||||
|
|
||||||
|
// x hsa type i32
|
||||||
|
// for x in v { // this moves v
|
||||||
|
// println!("{x}");
|
||||||
|
// }
|
||||||
|
|
||||||
|
// println!("{v:?}"); // ERROR v is already moved
|
||||||
|
|
||||||
|
let mut v = Vec::new();
|
||||||
|
for i in 0..10 {
|
||||||
|
v.push(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
double(&mut v);
|
||||||
|
println!("{v:?}");
|
||||||
|
|
||||||
|
triple(&mut v); // you can pass vectors as slices also
|
||||||
|
println!("{v:?}");
|
||||||
|
|
||||||
|
triple(&mut v[1..4]); // can create sub slices
|
||||||
|
println!("{v:?}");
|
||||||
|
}
|
||||||
|
|
||||||
|
fn double(v: &mut Vec<i32>) {
|
||||||
|
for x in v {
|
||||||
|
*x *= 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn triple(s: &mut [i32]) {
|
||||||
|
for x in s {
|
||||||
|
*x *= 3
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in new issue
Block a user