added more examples

This commit is contained in:
andy 2021-06-21 17:13:01 +01:00
parent c1e100650c
commit a7536995cc
12 changed files with 415 additions and 62 deletions

1
.gitignore vendored
View File

@ -1 +1,2 @@
/target /target
hello.txt

2
Cargo.lock generated
View File

@ -71,7 +71,7 @@ dependencies = [
] ]
[[package]] [[package]]
name = "rusty-playground" name = "rustyplayground"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"rand", "rand",

View File

@ -1,5 +1,5 @@
[package] [package]
name = "rusty-playground" name = "rustyplayground"
version = "0.1.0" version = "0.1.0"
authors = ["aj <andrewjpack@gmail.com>"] authors = ["aj <andrewjpack@gmail.com>"]
edition = "2018" edition = "2018"

62
src/collections.rs Normal file
View File

@ -0,0 +1,62 @@
use std::collections::HashMap;
// tuples and arrays
// both stack-based
pub fn compound() {
let tup = (500, 'a');
let (_, second) = tup;
println!("tuple: {}/{}", tup.0, second);
// all of same type, [u8; 4] = 4 u8 types
let _arr: [u8; 4] = [1, 2, 3, 4];
let repeater = [3; 5]; // broadcasts 5 elements of 3
println!("Retrieving from array: {}", repeater[3]);
}
pub fn vectors() {
let v: Vec<i32> = Vec::new();
let mut v = vec![1, 2, 3, 4];
v.push(5);
let mut v: Vec<_> = v.iter().map(|x| x + 1).collect();
println!("{:?}", v);
println!("2nd element is {}, {}",
&v[1], // will crash with index-out-of-bounds
v.get(1).unwrap() // get an option to handle gracefully
);
for i in &mut v{
*i += 1;
println!("item: {}", i);
}
}
pub fn hash() {
let mut map = HashMap::new();
map.insert("a".to_string(), 5);
map.insert("b".to_string(), 6);
map.insert("b".to_string(), 7); // overwrites
// map.insert("c".to_string(), 10);
map.entry("c".to_string()).or_insert(8);
println!("{:?}", map);
for (key, val) in map {
println!("{}: {}", key, val);
}
let text = "hello world wonderful world";
let mut map = HashMap::new();
for word in text.split_whitespace() {
let count = map.entry(word).or_insert(0);
*count += 1;
}
println!("{:?}", map);
}

View File

@ -13,6 +13,7 @@ mod iterate {
impl Iterator for Counter { impl Iterator for Counter {
type Item = u32; type Item = u32;
/// Get next item from the iterator
fn next(&mut self) -> Option<Self::Item> { fn next(&mut self) -> Option<Self::Item> {
if self.count < 5 { if self.count < 5 {
self.count += 1; self.count += 1;

28
src/lib.rs Normal file
View File

@ -0,0 +1,28 @@
//! Crate documentation
/// Print hello world to the screen
/// # Title
pub fn print_hello(){
println!("Hello World!");
}
/// Return sum of input
///
/// # Examples
/// ```
/// let z = rustyplayground::add(1, 2);
///
/// assert_eq!(3, z)
/// ```
pub fn add(x: isize, y: isize) -> isize {
x + y
}
pub mod new_mod {
//! # Documented module
//!
pub fn fun() {
}
}

35
src/lifetimes.rs Normal file
View File

@ -0,0 +1,35 @@
// declare lifetime after function name like generic type
// both parameters have same lifetime and must be alive when returned
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
if x.len() > y.len() {
x
} else {
y
}
}
// doesn't change lifetimes of parameters, just annotates enough
// that the compiler can reject stuff that won't work
// structs can have reference members
// annotate with lifetimes to ensure struct doesn't outlive reference
struct ImportantExcerpt<'a> {
part: &'a str,
}
// generic types, trait bounds and lifetimes
fn longest_with_an_announcement<'a, T>(
x: &'a str,
y: &'a str,
ann: T,
) -> &'a str
where
T: Display,
{
println!("Announcement! {}", ann);
if x.len() > y.len() {
x
} else {
y
}
}

View File

@ -6,6 +6,20 @@ macro_rules! log {
} }
} }
#[macro_export]
macro_rules! simple_vec {
// comma is literal, comma indicates zero or more
( $( $x:expr ),* ) => {
{
let mut temp_vec = Vec::new();
$(
temp_vec.push($x);
)*
temp_vec
}
};
}
#[macro_export] #[macro_export]
macro_rules! expr_stringer { macro_rules! expr_stringer {
// This macro takes an expression of type `expr` and prints // This macro takes an expression of type `expr` and prints

View File

@ -1,20 +1,32 @@
use std::io;
use std::cmp::Ordering; use std::cmp::Ordering;
use std::fs::File;
use std::io::{self, Read, ErrorKind};
use rand::Rng; use rand::Rng;
// use rustyplayground;
mod iterate; mod iterate;
mod macros; mod macros;
mod structs;
mod collections;
mod threads;
fn main() { fn main() {
basics(); // rustyplayground::print_hello();
compare(); // basics();
loops(); // compare();
vars(); // loops();
compound(); // vars();
// collections::compound();
// collections::vectors();
collections::hash();
threads::start_threads();
threads::thread_channel();
println!("testing returns: {}", returning(2)); // println!("testing returns: {}", returning(2));
strings(); // strings();
nullables(); // nullables();
nested_error_matching();
} }
fn basics() { fn basics() {
@ -47,9 +59,9 @@ fn basics() {
let r_num = rand::thread_rng().gen_range(1, 101); let r_num = rand::thread_rng().gen_range(1, 101);
println!("random number: {}", r_num); println!("random number: {}", r_num);
let vec = build_vector3(1, 2, 3); let vec = structs::build_vector3(1, 2, 3);
println!("Vector: {}/{}/{}", vec.x, vec.y, vec.z); println!("Vector: {}/{}/{}", vec.x, vec.y, vec.z);
let vec2 = update_x(vec); let vec2 = structs::update_x(vec);
println!("Vector2: {:#?}", vec2) println!("Vector2: {:#?}", vec2)
} }
@ -110,16 +122,6 @@ fn vars() {
let _f = 2.0; // defaults to 64 bit let _f = 2.0; // defaults to 64 bit
} }
fn compound() {
let tup = (500, 'a');
let (_, second) = tup;
println!("tuple: {}/{}", tup.0, second);
let _arr: [u8; 4] = [1, 2, 3, 4];
let repeater = [3; 5]; // stretches to 5 elements of 3
println!("Retrieving from array: {}", repeater[3]);
}
fn returning(input: i32) -> i32 { fn returning(input: i32) -> i32 {
let _stuff = 0; let _stuff = 0;
@ -132,51 +134,28 @@ fn returning(input: i32) -> i32 {
fn strings() { fn strings() {
let mut s = String::from("hello"); let mut s = String::from("hello");
let s2 = "world!".to_string();
let s3 = String::from("hello");
// cannot [] index strings due to utf-8 encoding
s.push_str(", world!"); s.push_str(", world!");
println!("Sliced: {}", &s[4..8]); println!("Sliced: {}", &s[4..8]); // slice
} println!("Appended: {}", s3 + " 2"); // takes ownership of s3
println!("{}",
format!("{} {}", s, s2)
);
#[derive(Debug)] let s4 = "abcd".to_string();
struct Vector3 { for i in s4.chars() {
x: i32, println!("{}", i);
y: i32,
z: i32,
}
impl Vector3 {
fn dot(&self, other: &Vector3) -> i32 {
self.x * other.x
+
self.y * other.y
+
self.z * other.z
} }
}
fn build_vector3(x: i32, y: i32, z: i32) -> Vector3 { for i in s4.bytes() {
Vector3 { println!("{}", i);
x, y, z
} }
} }
fn update_x(vec: Vector3) -> Vector3 {
Vector3 {
x: 5,
..vec
}
}
enum ColourChannel {
Red,
Green,
Blue
}
enum IpAddr {
V4(u8, u8, u8, u8),
V6(String),
}
fn nullables() { fn nullables() {
let _some_number = Some(5); let _some_number = Some(5);
let _some_string = Some("a string"); let _some_string = Some("a string");
@ -184,7 +163,71 @@ fn nullables() {
let _absent_number: Option<i32> = None; let _absent_number: Option<i32> = None;
} }
fn nested_error_matching() {
let f = File::open("hello.txt");
// .unwrap() get inner value or panic
// .expect() as above but with custom error message
let f = match f {
Ok(file) => file,
Err(error) => match error.kind() {
ErrorKind::NotFound => match File::create("hello.txt") {
Ok(fc) => fc,
Err(e) => panic!("Problem creating the file: {:?}", e),
},
other_error => {
panic!("Problem opening the file: {:?}", other_error)
}
},
};
let f = File::open("hello.txt").unwrap_or_else(|error| {
if error.kind() == ErrorKind::NotFound {
File::create("hello.txt").unwrap_or_else(|error| {
panic!("Problem creating the file: {:?}", error);
})
} else {
panic!("Problem opening the file: {:?}", error);
}
});
}
fn propagate_err() -> Result<String, io::Error> {
let f = File::open("hello.txt");
let mut f = match f {
Ok(file) => file,
Err(e) => return Err(e),
};
let mut s = String::new();
match f.read_to_string(&mut s) {
Ok(_) => Ok(s),
Err(e) => Err(e),
}
}
fn propagate_err_operator() -> Result<String, io::Error> {
let mut f = File::open("hello.txt")?;
let mut s = String::new();
f.read_to_string(&mut s)?; // continue if ok, return error if not, convert to return type if required
Ok(s)
}
fn propagate_err_operator_shorter() -> Result<String, io::Error> {
// can also be done with fs::read_to_string()
let mut s = String::new();
File::open("hello.txt")?.read_to_string(&mut s)?; // continue if ok, return error if not, convert to return type if required
Ok(s)
}
#[cfg(test)] #[cfg(test)]
// #[warn(unused_imports)]
mod tests { mod tests {
use super::*; use super::*;
@ -192,4 +235,21 @@ mod tests {
fn test1() { fn test1() {
assert_eq!(2, 1 + 1); assert_eq!(2, 1 + 1);
} }
#[ignore]
#[test]
#[should_panic(expected = "index out of bounds")] // check that panic message is substring of actual
fn test_panic() {
let arr = vec![1, 2, 3];
arr[4];
}
#[test]
fn test_result() -> Result<(), String> {
if 2 + 2 == 4 {
Ok(())
} else {
Err("Error".to_string())
}
}
} }

11
src/pointers.rs Normal file
View File

@ -0,0 +1,11 @@
// indireaction of box lets list be a fixed size
enum List {
Cons(i32, Box<List>),
Nil,
}
fn box_ptr() {
let b = Box::new(5); // implements deref and drop
println!("b = {}", b);
}

84
src/structs.rs Normal file
View File

@ -0,0 +1,84 @@
// and enums
use std::fmt::Display;
pub trait Euclidean {
fn cross();
fn magnitude() {
println!("Hello World");
}
}
#[derive(Debug)]
pub struct Vector3 {
pub x: i32,
pub y: i32,
pub z: i32,
}
impl Vector3 {
fn dot(&self, other: &Vector3) -> i32 {
self.x * other.x
+
self.y * other.y
+
self.z * other.z
}
}
impl Euclidean for Vector3 {
fn cross() {}
}
// FIELD INIT SHORTHAND
pub fn build_vector3(x: i32, y: i32, z: i32) -> Vector3 {
Vector3 {
x, y, z
}
}
// STRUCT UPDATE SYNTAX
pub fn update_x(vec: Vector3) -> Vector3 {
Vector3 {
x: 5,
..vec
}
}
// use trait as a parameter type
pub fn compound_mag(x: &impl Euclidean,
y: &(impl Euclidean + Display)) // multiple required traits
{
}
// above is sugar for below, restrictions on generic types
pub fn compound_mag_long<T: Euclidean + Display>(x: &T)
-> impl Display // specify just traits of a return type
{
5 // for display trait
}
// use where for easier reading
pub fn compound_mag_where<T>(x: &T)
where T: Euclidean + Display {
}
enum ColourChannel {
Red,
Green,
Blue
}
#[derive(Debug)]
enum IpAddr {
V4(u8, u8, u8, u8),
V6(String),
}
// can add methods to enums as well
impl IpAddr {
fn print(&self) {
println!("{:?}", self);
}
}

57
src/threads.rs Normal file
View File

@ -0,0 +1,57 @@
use std::thread;
use std::time::Duration;
use std::sync::mpsc;
// 1:1 threads
pub fn start_threads() {
let v = vec![1, 2, 3, 4];
// use move to transfer data into new thread
let handle = thread::spawn(move || {
println!("{:?}", v);
for i in v {
println!("{} from separate thread", i);
}
});
handle.join().unwrap();
thread::sleep(Duration::from_millis(5));
}
pub fn thread_channel() {
let (tx, rx) = mpsc::channel();
// use move to transfer data into new thread
thread::spawn(move || {
tx.send("Hello message!".to_string()).unwrap();
});
let rec = rx.recv().unwrap();
println!("{}", rec);
// MULTIPLE
let (tx, rx) = mpsc::channel();
// use move to transfer data into new thread
thread::spawn(move || {
let vals = vec![
String::from("h"),
String::from("e"),
String::from("l"),
String::from("l"),
String::from("o"),
];
for val in vals {
tx.send(val).unwrap();
thread::sleep(Duration::from_millis(200));
}
});
for rec in rx {
println!("{}", rec);
}
}