Makindo Medical Notes"One small step for man, one large step for Makindo" |
|
---|---|
Download all this content in the Apps now Android App and Apple iPhone/Pad App | |
MEDICAL DISCLAIMER: The contents are under continuing development and improvements and despite all efforts may contain errors of omission or fact. This is not to be used for the assessment, diagnosis, or management of patients. It should not be regarded as medical advice by healthcare workers or laypeople. It is for educational purposes only. Please adhere to your local protocols. Use the BNF for drug information. If you are unwell please seek urgent healthcare advice. If you do not accept this then please do not use the website. Makindo Ltd. |
Rust is a systems programming language focused on safety, speed, and concurrency. It aims to provide a safe and concurrent alternative to languages like C and C++ while ensuring memory safety and preventing data races. This guide provides an overview of the Rust programming language, its features, and basic syntax.
fn main() {
println!("Hello, world!");
}
This simple program prints "Hello, world!" to the console. The fn main()
defines the main function, which is the entry point of every Rust program. The println!
macro prints the text to the console.
In Rust, variables are immutable by default. To make a variable mutable, you must use the mut
keyword.
fn main() {
let x = 5; // Immutable variable
let mut y = 10; // Mutable variable
println!("x: {}, y: {}", x, y);
y += 5;
println!("Updated y: {}", y);
}
Rust has several built-in data types, including scalar types (integers, floating-point numbers, booleans, characters) and compound types (tuples, arrays).
fn main() {
let integer: i32 = 42;
let float: f64 = 3.14;
let boolean: bool = true;
let character: char = 'R';
println!("Integer: {}, Float: {}, Boolean: {}, Character: {}", integer, float, boolean, character);
let tuple: (i32, f64, u8) = (500, 6.4, 1);
let (x, y, z) = tuple;
println!("Tuple values: {}, {}, {}", x, y, z);
let array: [i32; 3] = [1, 2, 3];
println!("Array values: {}, {}, {}", array[0], array[1], array[2]);
}
Rust provides standard control flow constructs such as if
statements, loop
, while
, and for
loops.
fn main() {
let number = 7;
if number < 5 {
println!("Number is less than 5");
} else {
println!("Number is greater than or equal to 5");
}
let mut counter = 0;
let result = loop {
counter += 1;
if counter == 10 {
break counter * 2;
}
};
println!("Result from loop: {}", result);
let mut n = 3;
while n != 0 {
println!("{}!", n);
n -= 1;
}
println!("LIFTOFF!!!");
let array = [10, 20, 30, 40, 50];
for element in array.iter() {
println!("The value is: {}", element);
}
}
Rust's ownership model ensures memory safety without a garbage collector. The key concepts are ownership, borrowing, and lifetimes.
fn main() {
let s1 = String::from("hello");
let s2 = s1; // s1 is moved to s2, and s1 is no longer valid
// println!("{}", s1); // This would cause a compile-time error
println!("{}", s2);
let s3 = String::from("world");
let s4 = &s3; // s4 is a reference to s3, and s3 remains valid
println!("{}", s3);
println!("{}", s4);
let mut s5 = String::from("hello");
let s6 = &mut s5; // Mutable reference to s5
s6.push_str(", world");
println!("{}", s6);
}
Rust uses the Result
and Option
types for error handling, promoting robust and explicit error management.
fn main() {
let result: Result = divide(10, 2);
match result {
Ok(value) => println!("Result: {}", value),
Err(error) => println!("Error: {}", error),
}
}
fn divide(a: i32, b: i32) -> Result {
if b == 0 {
Err(String::from("Division by zero"))
} else {
Ok(a / b)
}
}
Rust is a powerful systems programming language that emphasizes safety, speed, and concurrency. Its unique ownership model and type system prevent many common programming errors, making it an excellent choice for a wide range of applications. This guide covers the basics, but there's much more to explore in Rust's rich ecosystem.
Rust is a systems programming language that focuses on safety, speed, and concurrency. It offers memory safety without garbage collection, making it an excellent choice for performance-critical applications. This guide covers a wide range of topics in Rust programming, including basic syntax, advanced features, algorithms, and data structures.
fn main() {
println!("Hello, world!");
}
This simple program prints "Hello, world!" to the console. The fn main()
defines the main function, which is the entry point of every Rust program. The println!
macro prints the text to the console.
In Rust, variables are immutable by default. To make a variable mutable, you must use the mut
keyword.
fn main() {
let x = 5; // Immutable variable
let mut y = 10; // Mutable variable
println!("x: {}, y: {}", x, y);
y += 5;
println!("Updated y: {}", y);
}
Rust has several built-in data types, including scalar types (integers, floating-point numbers, booleans, characters) and compound types (tuples, arrays).
fn main() {
let integer: i32 = 42;
let float: f64 = 3.14;
let boolean: bool = true;
let character: char = 'R';
println!("Integer: {}, Float: {}, Boolean: {}, Character: {}", integer, float, boolean, character);
let tuple: (i32, f64, u8) = (500, 6.4, 1);
let (x, y, z) = tuple;
println!("Tuple values: {}, {}, {}", x, y, z);
let array: [i32; 3] = [1, 2, 3];
println!("Array values: {}, {}, {}", array[0], array[1], array[2]);
}
Rust provides standard control flow constructs such as if
statements, loop
, while
, and for
loops.
fn main() {
let number = 7;
if number < 5 {
println!("Number is less than 5");
} else {
println!("Number is greater than or equal to 5");
}
let mut counter = 0;
let result = loop {
counter += 1;
if counter == 10 {
break counter * 2;
}
};
println!("Result from loop: {}", result);
let mut n = 3;
while n != 0 {
println!("{}!", n);
n -= 1;
}
println!("LIFTOFF!!!");
let array = [10, 20, 30, 40, 50];
for element in array.iter() {
println!("The value is: {}", element);
}
}
Functions are declared using the fn
keyword. Rust supports functions with parameters and return values.
fn main() {
let sum = add(5, 3);
println!("Sum: {}", sum);
}
fn add(a: i32, b: i32) -> i32 {
a + b
}
Rust's ownership model ensures memory safety without a garbage collector. The key concepts are ownership, borrowing, and lifetimes.
fn main() {
let s1 = String::from("hello");
let s2 = s1; // s1 is moved to s2, and s1 is no longer valid
// println!("{}", s1); // This would cause a compile-time error
println!("{}", s2);
let s3 = String::from("world");
let s4 = &s3; // s4 is a reference to s3, and s3 remains valid
println!("{}", s3);
println!("{}", s4);
let mut s5 = String::from("hello");
let s6 = &mut s5; // Mutable reference to s5
s6.push_str(", world");
println!("{}", s6);
}
Rust uses the Result
and Option
types for error handling, promoting robust and explicit error management.
fn main() {
let result: Result = divide(10, 2);
match result {
Ok(value) => println!("Result: {}", value),
Err(error) => println!("Error: {}", error),
}
}
fn divide(a: i32, b: i32) -> Result {
if b == 0 {
Err(String::from("Division by zero"))
} else {
Ok(a / b)
}
}
Structs and enums are used to create custom data types in Rust.
struct User {
username: String,
email: String,
sign_in_count: u64,
active: bool,
}
fn main() {
let user1 = User {
username: String::from("john_doe"),
email: String::from("john@example.com"),
sign_in_count: 1,
active: true,
};
println!("Username: {}", user1.username);
}
enum IpAddrKind {
V4(String),
V6(String),
}
fn main() {
let home = IpAddrKind::V4(String::from("127.0.0.1"));
let loopback = IpAddrKind::V6(String::from("::1"));
match home {
IpAddrKind::V4(addr) => println!("IPv4: {}", addr),
IpAddrKind::V6(addr) => println!("IPv6: {}", addr),
}
}
Traits define shared behavior, and generics allow for code reuse with different types.
trait Summary {
fn summarize(&self) -> String;
}
struct Post {
title: String,
content: String,
}
impl Summary for Post {
fn summarize(&self) -> String {
format!("{}: {}", self.title, self.content)
}
}
fn main() {
let post = Post {
title: String::from("Hello, world!"),
content: String::from("This is my first post."),
};
println!("{}", post.summarize());
}
fn largest(list: &[T]) -> &T {
let mut largest = &list[0];
for item in list {
if item > largest {
largest = item;
}
}
largest
}
fn main() {
let numbers = vec![34, 50, 25, 100, 65];
let result = largest(&numbers);
println!("The largest number is {}", result);
}
Example of bubble sort in Rust:
fn bubble_sort(arr: &mut [i32]) {
let mut n = arr.len();
while n > 1 {
let mut last_modified = 0;
for i in 1..n {
if arr[i - 1] > arr[i] {
arr.swap(i - 1, i);
last_modified = i;
}
}
n = last_modified;
}
}
fn main() {
let mut arr = [64, 34, 25, 12, 22, 11, 90];
bubble_sort(&mut arr);
println!("Sorted array: {:?}", arr);
}
Example of binary search in Rust:
fn binary_search(arr: &[i32], target: i32) -> Option {
let mut left = 0;
let mut right = arr.len() - 1;
while left <= right {
let mid = left + (right - left) / 2;
if arr[mid] == target {
return Some(mid);
} else if arr[mid] < target {
left = mid + 1;
} else {
right = mid - 1;
}
}
None
}
fn main() {
let arr = [2, 3, 4, 10, 40];
let target = 10;
match binary_search(&arr, target) {
Some(index) => println!("Element found at index {}", index),
None => println!("Element not found in array"),
}
}
Vectors are resizable arrays. Here's how you can use them:
fn main() {
let mut v: Vec = Vec::new();
v.push(1);
v.push(2);
v.push(3);
for i in &v {
println!("{}", i);
}
match v.get(2) {
Some(third) => println!("The third element is {}", third),
None => println!("There is no third element."),
}
}
HashMap is a collection of key-value pairs. Here's an example:
use std::collections::HashMap;
fn main() {
let mut scores = HashMap::new();
scores.insert(String::from("Blue"), 10);
scores.insert(String::from("Yellow"), 50);
let team_name = String::from("Blue");
let score = scores.get(&team_name);
match score {
Some(score) => println!("The score for {} is {}", team_name, score),
None => println!("No score found for {}", team_name),
}
for (key, value) in &scores {
println!("{}: {}", key, value);
}
}
Implementing a simple singly linked list:
use std::rc::Rc;
use std::cell::RefCell;
type Link = Option>>;
struct Node {
value: i32,
next: Link,
}
struct LinkedList {
head: Link,
}
impl LinkedList {
fn new() -> Self {
LinkedList { head: None }
}
fn append(&mut self, value: i32) {
let new_node = Rc::new(RefCell::new(Node { value, next: None }));
match self.head {
Some(ref head) => {
let mut current = head.clone();
while let Some(ref next) = current.borrow().next {
current = next.clone();
}
current.borrow_mut().next = Some(new_node);
}
None => {
self.head = Some(new_node);
}
}
}
fn display(&self) {
let mut current = self.head.clone();
while let Some(ref node) = current {
print!("{} -> ", node.borrow().value);
current = node.borrow().next.clone();
}
println!("None");
}
}
fn main() {
let mut list = LinkedList::new();
list.append(1);
list.append(2);
list.append(3);
list.display();
}
Implementing a simple binary tree:
use std::rc::Rc;
use std::cell::RefCell;
type TreeLink = Option>>;
struct TreeNode {
value: i32,
left: TreeLink,
right: TreeLink,
}
struct BinaryTree {
root: TreeLink,
}
impl BinaryTree {
fn new() -> Self {
BinaryTree { root: None }
}
fn insert(&mut self, value: i32) {
let new_node = Rc::new(RefCell::new(TreeNode {
value,
left: None,
right: None,
}));
match self.root {
Some(ref root) => Self::insert_node(root.clone(), new_node),
None => self.root = Some(new_node),
}
}
fn insert_node(current: Rc>, new_node: Rc>) {
if new_node.borrow().value < current.borrow().value {
match current.borrow().left {
Some(ref left) => Self::insert_node(left.clone(), new_node),
None => current.borrow_mut().left = Some(new_node),
}
} else {
match current.borrow().right {
Some(ref right) => Self::insert_node(right.clone(), new_node),
None => current.borrow_mut().right = Some(new_node),
}
}
}
fn inorder_traversal(&self) {
Self::traverse_inorder(self.root.clone());
}
fn traverse_inorder(node: TreeLink) {
if let Some(ref node) = node {
Self::traverse_inorder(node.borrow().left.clone());
print!("{} ", node.borrow().value);
Self::traverse_inorder(node.borrow().right.clone());
}
}
}
fn main() {
let mut tree = BinaryTree::new();
tree.insert(10);
tree.insert(5);
tree.insert(15);
tree.insert(3);
tree.insert(7);
tree.insert(13);
tree.insert(18);
println!("Inorder traversal:");
tree.inorder_traversal();
}
Rust's ownership model guarantees thread safety, making it an excellent choice for concurrent programming. Here’s a basic example using threads:
use std::thread;
use std::time::Duration;
fn main() {
let handle = thread::spawn(
|
| {
for i in 1..10 {
println!("hi number {} from the spawned thread!", i);
thread::sleep(Duration::from_millis(1));
}
});
for i in 1..5 {
println!("hi number {} from the main thread!", i);
thread::sleep(Duration::from_millis(1));
}
handle.join().unwrap();
}
Rust provides async/await syntax for asynchronous programming. Here’s a basic example:
use tokio::time::{sleep, Duration};
#[tokio::main]
async fn main() {
let handle = tokio::spawn(async {
for i in 1..10 {
println!("hi number {} from the spawned task!", i);
sleep(Duration::from_millis(1)).await;
}
});
for i in 1..5 {
println!("hi number {} from the main task!", i);
sleep(Duration::from_millis(1)).await;
}
handle.await.unwrap();
}
Rust can also be used for web development. Here's a basic example using the Actix-web framework:
use actix_web::{web, App, HttpServer, Responder};
async fn greet() -> impl Responder {
"Hello, world!"
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
HttpServer::new(
|
| {
App::new()
.route("/", web::get().to(greet))
})
.bind("127.0.0.1:8080")?
.run()
.await
}
Rust is a powerful systems programming language that emphasizes safety, speed, and concurrency. Its unique ownership model and type system prevent many common programming errors, making it an excellent choice for a wide range of applications. This guide covers the basics, but there's much more to explore in Rust's rich ecosystem.