let some_immutable_var = 42; // i32 typing inferred
// Would crash: some_immutable_var += 3;
let mut mutable_var = 3.14;
mutable_var += 1.78;
const SOME_CONST = 1984; // Must be a compile-time expression
-
Tuples
-
May group different types
-
Fixed length
-
Acesso tup.0 (tup.IDX)
-
let tup : (i32, f64, u8) = (500, 6.4, 1);
let a = tup.0; // a = 500;
let (x, y, z) = tup; // Destructuring
-
Array
-
Fixed size
-
Panics when trying to access out of bounds
-
let myarr : [i32, 5] = [5, 4, 3, 2, 1];
let x = myarr[2];
let y = myarr[5]; // PANIC!!!
-
Last expression in a block is the return value from the block if
;
is absent -
if
can be used in place of a ternary operator-
let number = if condition { something } else { another_thing };
-
-
loop
makes an infinite loop-
Exits with
break
-
The expression after
break
is the return value.
-
let mut i = 0;
let result = loop {
i += 1;
if i == 5 {
break i * 3;
}
};
-
while
is likeloop
, but with a checking condition-
But does not return a value
-
-
for
goes over elements in an iterator
let col = [1, 2, 3, 5, 8, 13, 21];
for element in col.iter() {
println!("Element is {}", element);
}
-
Stack vs heap
-
Rules
-
Each value has a variable that is its //Owner//
-
There can be a single owner at a time
-
The the owner goes out of scope, the value is destroyed
-
-
Stack stored types are just copied around
-
String
as an example of heap stored value -
Moving
-
Assignment moves data from an owner to a new one
-
-
Copy
trait-
The
Copy
trait allows owners to be copied instead of moved -
Can’t be mixed with the
Drop
trait -
Simple scalar values
-
Tuples of all fields implementing the Copy trait
-
-
Passing arguments to a function
-
Same semantics as assignment
-
Parameters are either moved or copied
-
-
Returning values from functions
-
Immutable references
-
There can be multiple immutable refs
-
NOP when go out of scope
-
-
Single mutable reference at a give scope
-
Also no immutable references while there is one mutable around
-
-
"Views" into the string
-
Byte addressed
-
Means an immutable borrow into the string
-
-
Syntax for creating:
&s[start..end]
-
Indexes similar to python
-
Indexes optionals
-
Indexes must be in the boundaries of UTF8 chars
-
-
Syntax for returning:
&str
-
String literals are also slices
-
Meaning they are immutable borrows
-
-
String slices can be used as parameter type for greater flexibility than regular parameters
-
Slices can be used for other collections too, like
&[i32]
for arrays of i32
struct Vector {
x: f64,
y: f64,
z: f64,
}
struct Color(i32, i32, i32);
struct Point(i32, i32, i32);
let c = Color(0, 0, 0);
let p = Point(0, 0, 0);
-
Despite having the same "value",
c
andp
have different types. -
Can be deconstructed like regular tuples
-
Struct ownership of references owned by someone else requires lifetime tags.
-
Unit-like structs have no fields
-
Useful for trait tags
-
-
Struct ownership of references owned by someone else requires lifetime tags.
-
Use the
#[derive(Debug)]
macro in the struct declaration to allow printing it.
-
Methods go inside an
impl NAME
block -
With
self
first parameter, with the type of the Struct-
But the same modifiers of mutable, borrow applies here
-
-
Associated methods
-
Like "static" methods. Plain functions namespaced in the class.
-
Accessed with
::
separator instead of just.
-
-
Can have multiple impl blocks
enum IpAddrKind {
V4,
V6,
}
//...
let x = IpAddrKind::V4;
enum IpAddr {
V4(u8, u8, u8, u8),
V6(String),
}
//...
let x = IpAddr::V4(127, 0, 0, 1);
struct Ipv4Addr{
//
}
struct Ipv6ADdr{
//
}
enum IpAddr {
V4(Ipv4Addr),
V6(Ipv6Addr),
}
...
let x = IpAddr::V4(127, 0, 0, 1);
-
Enums can also have impl blocks to implement Methods
enum Option<T> {
Some(T),
None,
}
let someNumber = Some(5);
let absentNumber : Option<i32> = None;
-
Need to handle all enum values in order to extract info from it.
enum Coin {
Penny,
Nickel,
Dime,
Quarter,
}
fn value_in_cents(coin: &Coin) -> u8 {
match coin {
Coin::Penny => 1,
Coin::Nickel => 5,
Coin::Dime => 10,
Coin::Quarter => 25,
}
}
match opt {
None -> None,
Some(i) -> Some(i+1),
}
-
_
used as a placeholder for remaining values in the match
if let Some(3) = some_expression {
// do something
}
-
Packages: A cargo feature that lets you build, test and share crates
-
Crates: A tree of modules that produce a library or executable
-
Modules and use: Control the organization, scope and privacy of paths
-
Paths: A way to name an item (the item’s full qualified name?)
-
Crate is a binary or library
-
Crate root is the file the compiler starts from
-
A package is formed by one or more crates
-
The package contains a Cargo.toml file describing how to build these crates
-
Must contain at least one crate (either binary or library)
-
At most one library crate
-
Any number of binary crates
-
-
-
Convention of
src/main.rs
as the crate root of a binary crate with the same name -
Likewise,
src/lib.rs
is the convention for a library crate with the same name -
Each file in
src/bin.rs
means a new separate binary crate -
Crates expose functionality through a scope with the crate name
-
Modules control visibility of stuff
-
Parent/child/sibling naming for their relationship
-
Modules can be accessed by absolute path by using the root
crate
:-
crate::front_of_house::add_to_waitlist();
-
-
Also by relative path by using
self
,super
or a local identifier to the current module.-
mod_in_current_namespace::func();
-
super
refers to the parent module
-
-
Private by default
-
Child modules can use private stuff from parent modules
-
Parent modules can’t use private stuff from child modules
-
Think of child modules as implementation details
-
Use
pub
to make stuff visible-
Needs to be applied to both the module and the members you want to expose.
-
-
Struct fields are also private by default
-
You can make fields public on a case by case basis
-
-
Enum fields are all public if the enum is public
-
Makes sense, as you may need to match all enum values
-
-
use
works like Python’sfrom parent import module
, in the sense of makingmodule
available in the current scope by its name-
Also has the option to use
as
to replace the name -
Also have the option to import everything with the
*
name-
use std::collections::*;
-
-
-
Idiomatic ways of using
use
:-
Functions are imported keeping their declaring module as a name qualifier
-
Structs and Enums are imported directly
-
-
Using
pub use
to re-export a name to whoever imports us -
Multiple uses with the same prefix can be grouped together
-
use std::io::{self, Write};
-
-
Vector
-
Variable number of items contiguously
-
-
String
-
Collection of characters
-
-
HashMap
-
Associate a value to a particular Key
-
Particular implementation of
map
-
let v1 : Vec<i32> = Vec::new();
{
let v = vec![1, 2, 3];
v1.push(1);
v1.push(2);
v1.push(3);
} // v is freed here
let v1 = vec![2,4,6,8];
let third = &v1[2]; // May panic if out of bounds
match v1.get(2) {
Some(third) => ...,
None => ...,
}
-
Holding a reference from a Vector item works like holding a reference to a vector.
let v = vec![1,2,3];
for i in &v {
println!("{}", i);
}
for i in &mut v {
*i += 50;
}
enum Cell {
Int(i32),
Float(f64),
Text(String),
}
let row = vec![
Cell::Int(3),
Cell::Float(3.14),
Cell::Text(String::from("duh")),
];