Rust Cheat Sheet
Rust Cheat Sheet
int, float bool, char A (compound) type can implement mut a: &T can point p to something else fn main() { function fn longest<'a>(x: &'a str, y: &'a str) -> &'a str { The function signature now
fn main() {
or use turbofish ::<type> after name of function within the block it is a: &mut T can mutate var pointed at by a let mut s = String::from("hello"); When we’re defining this function, fn longest(x: &str, y: &str) -> &str {
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
says that for some lifetime 'a,
returning the type let x: i32 = 17;
tuples containing copy types Copy if all of its components mut a: &mut T can change pointer and var pointed at
change(&mut s);
struct/ struct Borrowed<'a>(&'a i32) we don’t know the concrete values
declared in, which is {
}
if x.len() > y.len() {
if x.len() > y.len() {
the function will get two
types implementing copy trait implement Copy https://stackoverflow.com/questions/29672373/what- fn change(some_string: &mut String) {
enum struct ImportantExcerpt<'a> {
enum Either<'a> { that will be passed into this
parameters, both of which are
::<u32> denoted by brackets let y: i32 = 3;
is-difference-between-mut-a-t-and-a-mut-t
}
some_string.push_str(", world");
part: &'a str, Num(i32), function, so we don’t know x
x
string slices that live at least as
println!("x is {} and y is {}", x, y);
when an owning variable whether the if case or the else case } else {
} else {
Mo
default for heap variables
Ru o n n bo ow n
}
} Ref(&'a i32), long as the lifetime 'a.
V b mmu b b d u
will execute. We also don’t know
goes out of scoped, it is println!("x is {} and y is {}", x, y); // This "there can be only one" } y
y
the concrete lifetimes of the
dropped won't work.
static lifetime let s: &'static str = "I have a static lifetime." }
}
use mut keyword to } everything that is not copy is move you can only have one
mutablereference to a particular
we can use curly brackets to create a new scope,
allowing for multiplemutable references, just not
references that will be passed in,
The 'static lifetime is the entire so we can’t look at the scopes as w } }
let mut bar = 5 examples of move:
duration of the program
h dow n n op
piece of data in a particular scope simultaneous ones
declare var as mutable
assignment let s1 = String::from('hello') s1 no longer has value, We also cannot have a mutable multiple immutable references are okay because no
m o n u nd num
m on p o du
is moved to s2
reference while we have an one who is just reading the data has the ability to
shadowing a name does let x: i32 = 8;
let s2 = s1 calling s1 will lead to
when you do not have
immutableone. affect anyone else’s reading of the data to declare lifetimes structs that hold references need to
cleaner conversion let x = "12" println!("{}", x); // Prints "12".
let the_sum = sum_vector(s);
moved to argument if
passed to function call!!
need to specify lifetimes when: } }
between types with let x: usize = x.parse().unwrap() } println!("{:?}", s); //ERROR s has Deref coercion was added to Rust so that programmers writing function and method Its lifetime gets assigned let four = String::from("four"); let four = String::from("four");
println!("{}",x); //prints 8 moved into sum_vector 1. there is one input parameter.
same variable name calls don’t need to add as many explicit references and dereferences with & and *. to the output let hold_my_four = Holder{val: four}; let hold_my_four = Holder{val: &four};
Cons an s
compiler will insert as many * To print a memory address use :p 2. there are multiple parameters,
with struct and mutability change operations as necessary to get it right
Its lifetime gets assigned
or removes need for mut let x = 5 const THRESHOLD: i32 = 10; placeholder
but one is &self or &mut self. to output
let mut point = Point { x: 0, y: 0 };
let x = x+1 f.foo();
let x = 1;
type of the value must always point.x = 5;
(&f).foo();
println!("x: {}, address: {:p}", &x, &x);
be annotated const T: usize = 20; let point = point; // now immutable
(&&f).foo();
// x: 1, address: #0x7ffc59c6591c
if compiler can't figure out lifetime based on these rules, lifetime
both can use first value when assigning second (or more) time point.y = 6; // this causes an error
always immutable fn main() { annotation is needed
Constants can be declared in any println!("{}", T);
scope, including the global scope }
Tup es
x: f64,
use single quotes grouping together some number of other values struct StructName{ struct Rectangle { Dog, Circle(Point, f64),
y: f64,
m m
}
1. define a struct 2. set defaults 3. declare using new or new with update
integers are a combination of: min or max value that u8::min_value() with avariety of types into one compound type Capital case is rust field: type, width: u32, let c= Config { Cat, Rectangle(Point, Point),
can be represented by let c = 'a' let c: char = 'A' let heart_eyed_cat = ' ' height: u32,
pub struct Config { impl Config {
u32 i16
w
num to char let c = 65u8 as char char::from_digit(4, 10) -> option<char>
A ays
} }
dependent on architecture assert_eq!(chars.next(), Some('a')); let red = Color(100, 0, 0) let Color(r,g,b) = red;
i only
10i8.signum() 10i8.abs() char from byte(s) fixed length container of some type declarating using update pattern .. let origin = Point(0, 0, 0) println!("{}", r); //100
let sparkle_heart = vec![240, 159, 146, 150]; let mut a: Animal = Animal::Dog("Cocoa".to_string(), 37.2)
-> option<char>
let sparkle_heart = str::from_utf8(&sparkle_heart)
flo n po n
.. will copy unspecified field with let mut point = Point3d { x: 0, y: 0, z: 0 }
let a :[type, size] type must have
Boo ean
c.is_digit(radix) c.is_ascii() this function only recognizes the let a = [1, 2, 3, 4, 5]; struct Kilometers(f64); let milage = Miles(20);
Dog(String, f64),
42.checked_rem(4) 13.checked_div(3) characters 0-9, a-z and A-Z
struct Point { let p = Point{ let Point { x: a, y: b } = p; to declare vars a and b struct Meters(f64); println!("{:?}", milage.0);
c.is_numeric() c.is_ascii_digit() x: i32, x: 2, Cat {name: String, weight: f64 },
let Point { x, y } = p; if var names match field names let Mile(m) = milage;
(-25).checked_mul(3) 32.checked_sub(1) y: i32, y:12, }
u only checked_next_power_of_two()
c.is_alphabetic() c.is_ascii_alphabetic()
A m see also "Methods for slices and vecs" } }
Structs are Move by default use derive to implement let c = Animal::Cat { name: "Spotty".to_string(), weight: 2.7 }
true or false
D fin m hod
c.is_alphanumeric() c.is_asci_alphanumeric() error if out of
a.get(idx) ->option array.len() copy and clone
a[idx] bounds implement by specifying impl block
true casts to 1 and false to 0
Con on c.is_ascii_lowercase() To enable print
use derive to Enum can have custom discriminant
c.is_ascii_uppercase()
c.is_lowercase() c.is_uppercase()
a.get_mut(idx) instance impl StructName{ impl Rectangle {
fn area(&self) -> u32 {
instance
method call:
implement Debug enum Foo { let baz_discriminant = Foo::Baz as u32;
true as i32 false as i32 fn func(&self, ...){..}
string/str <-> digit let four: u32 = "4".parse().unwrap() c.is_whitespace() c.is_ascii_whitespace() self.width * self.height see Traits for hash, defaults, copy Bar, // 0 assert_eq!(baz_discriminant, 123);
instance } } rect.area()
} Baz = 123,// 123
methods take #[derive(Debug, Copy, Clone)]
Boo n op o
c.is_ascii_punctuation()
o
Quux, // 124
let four = "4".parse::<u32>().unwrap() Returns an iterator that yields the lowercase let arr = [1, 2, 3]; self as first three variants, corresponding to the three &self if it’s a &mut self if it’s a self if it’s a value struct Rectangle {
equivalent of a char as one or more chars. kinds of things the struct instance could be: reference on the stack, }
parameter mutable reference width: u32,
u32::from_str_radix("A", 16) ->Ok(10) for c in &arr{...} or for x in arr.iter() { }
and not c.to_lowercase() c.to_uppercase()
}
height: u32,
you can implements methods on the size of an enum will not exceed the largest of
arrays are arrays in Rust have a this will error enums, just like you would on structs its variants plus as much as is needed for the tag
or xor char <-> digit '1'.to_digit(10) -> option<c> c.to_ascii_uppercase() c.to_ascii_lowercase() non-ASCII letters are unchanged let n = 10; static impl StructName{ impl Rectangle { static method call ::
let r1 = Rectangle{x:1,y:1};
stack allocated fixed / constant length let arr = [i32; n]//error!!
no self fn func(...)... fn area(width, height) -> u32 { let r2 = r1; //Copied, not moved thanks to copy, clone
rect::area(10,3) println!("copied, not moved {:?}, {:?}", r1, r2);
o d u u n num fi d m h p on
char::from_digit(4, 10) } width * height
}
c.len_utf8() num bytes in utf8
between 1 and 4 see also structs, vecs, hasmap, string for heap allocated compound types }
this technique is usually used when the
method transforms self into something else
and you want to prevent the caller from using
the original instance after the transformation
Str ngs Str ng s ce & Methods for Str ng / &str Vec<T> Array s ces Methods for s ces and vecs
"UTF-8 encoded growable string" Slices are a view into a block
P =Pattern s.rfind(char::is_whitespace)
heap allocated
has ownership over the contents s.rfind("asd") of memory represented as
char,&str or closure
stored on the heap
s.rfind('A')
containers of one type a pointer and a length
Add mo m
split s.split(P) s.rsplit(P) [[1, 2], [3, 4]].concat() // [1,2,3,4] x.sort().reverse();
A on inplace if mutable string only (no slice) str_slice.to_string() s.contains(P) s.is_empty() s.find(P) s.rfind(P)
"abc1def2ghi".split(char::is_numeric)
Vec only
with ["hello", "world"].join(" ") //"hello world"
v.sort_by_key(|k| k.abs())
s.starts_with(P) s.ends_with(P) add item vec.push(item)
add string literal hello.push_str("..?!") str <-> bytes s.find(|c:char|(c<'o') && (c>'a'))
let t = "abc1def2ghi".split(char::is_numeric);
vec.clear() seperator [[1, 2], [3, 4]].join(&0) // [1, 2, 0, 3, 4] v.sort_by(|a, b| a.cmp(b))
remove all values does not change capacity
"bors".as_bytes() as_bytes_mut s.is_char_boundary() s.is_ascii() assert_eq!(vec!["abc", "def", "ghi"], t.collect::<Vec<&str>>()); insert item vec.insert(index, item)
add char at end hello.push(char) -> &[u8]
let u:Vec<&str> = "abc1def2ghi".rsplit(char::is_numeric).collect(); v.swap(1, 3)
shorten vec vec.truncate(new_len) keeps the first len elements
and drops the rest
assert_eq!(vec!["ghi", "def", "abc"], u);
remove last item vec.pop()
no
returns item at index,
->option
v.swap_remove(1) vec only
insert str s.insert_str(index, &str)
Replacing patterns
swaps last item to index
str::from_utf8(&vec![240, 159, 146, 150]) -> String "lion::tiger::leopard".split("::").collect() vec.shrink_to_fit() -> bool
remove from index v.remove(index) shrink capacity
insert char s.insert(index,char) panics if out of index / not
on char boundary
from_utf8_mut -> Result<&str, err> string.replace(P, &str)
let s = "this is old";
assert_eq!("this is new", s.replace("old", "new"));
reserve capacity vec.reserve(10) Reserves capacity for at least
v.is_empty() v.contains(&30) other
splitn
additional more elements
returns at most N items
remove last char s.pop() option<char>
s.replacen(P, &str, count)
let s = "foo foo 123 foo"; remove and iterate slice v.drain(1..).collect() vec.capacity()
number of elements
the vector can hold
assert_eq!("new new 123 foo", s.replacen("foo", "new", 2));
assert_eq!("faa fao 123 foo", s.replacen('o', "a", 3)); let v: Vec<&str> = "Mary had a little lambda".splitn(3, ' ').collect();
Creates a draining iterator that removes the Remove consecutive
vec.dedup() v.starts_with(&[10]) v.starts_with(&[10, 40])
from index s.remove(index) char (or panics) let str_slice: &[&str] = &["one", "two", "three"] specified range in the vector and yields the
repeated elements
assert_eq!("foo foo new23 foo", s.replacen(char::is_numeric, "new", 1));
->["Mary", "had", "a little lambda"]
removed items. vec.len()
Iterate matches Removes all but the first of consecutive elements in
vec.dedup_by(|a, b| a.eq_ignore_ascii_case(b)) v.ends_with(&[10]) v.ends_with(&[10, 40])
split s.split_off(index_to_split_at) inplace = 0..t,
returned is t..n
append by clone vec1.extend(vec2); the vector satisfying a given equality relation.
s.matches(P) "1abc2abc3".matches(char::is_numeric).collect() leaves vec2 as is Removes all but the first of consecutive elements in
vec.dedup_by_key(|i| *i / 10);
-> ["1", "2", "3"] vec1.extend_from_slice(&[..]) the vector that resolve to the same key
see iter for maps / filters / plus many others
clear s.clear() removes contents, moves vals from vec2
keeps capacity
s.repeat(usize) filter/ retain v.retain(|a| a<10)
Retains only the elements
limit to size [n] one at a time over n elements of the slice at a time
last slice might for chunk in v.chunks_mut(2) {
overlap slice.windows(2) let slice = ['r', 'u', 's', 't']; ->ru, us, st, None
let mut iter = slice.windows(2);
Funct ons C osures closures can capture their environment and access
variables from the scope in which they’re defined
Match allows us to compare a value against a
series of patterns and then execute
code based on which pattern matches.
p
into iterator
match not in
returned vals
let slice = [10, 40, 33, 20];
let mut iter = slice.split(|num| num % 3 == 0);
assert_eq!(iter.next().unwrap(), &[10, 40]);
assert_eq!(iter.next().unwrap(), &[20]);
assert!(iter.next().is_none()); into two
D on fn add_one(x: usize)-> usize{
x+1
un on w h n use traits bounds to make sure that code
inside function works on the generic
n let closure = |arg1| {..} |par1, par2, ..| for multiple args
n match VALUE {
PATTERN => EXPRESSION,
Arm = PATTERN => VALUE
ho h nd a match that only cares
about matching one case
does not check
exhaustiveness
only accepts
refutable patterns let mut iter = vec.split(|num|num%3==0) let (left, right) = v.split_at(index)
(slice, slice)
0..index, index..n
or return value let add_one_v3 = |x| { x + 1 };
for every possible value type and length of value scoped locally
let favorite_color: Option<&str> = None;
for group in v.splitn_mut(n, predicate) {... if let Some((last, elements)) = x.split_last()
(multiple) else branches testing different variables
let age: Result<u8, _> = "34".parse();
T T T let add_one_v4 = |x| x + 1 ; let is_tuesday = false;
if let Some(color) = favorite_color {
vec.split_off(usize) Splits the collection into vec contains 0..usize,
|| for no args Match can assign a value or do something println!("Using, {}, as the background", color);
} else if is_tuesday {
Returns an iterator over subslices
separated by elements that match pred,
let v = [10, 40, 30, 20, 60, 50];
for group in v.splitn(2, |num| *num % 3 == 0) {
two at the given index returns usize..n
A um n W h bound
x.split_last_mut() x.split_first_mut() option
println!("{:?}", group);
Generics may use traits as doing so will limit use of func to let x = 5; let x = 1; if let Some(x) = 1...4{..} println!("Tuesday is green day!");
limited to returning at most n items
}
} else if let Ok(age) = age {
bounds on their type parameters types that implement trait let number = match x { match x { else if(condition){..}... ....
(i.e. [10, 40], [20, 60, 50]):
Fn traits 1 => "one", } else {
to force closure to take 1 => println!("one"),
Types of parameters must be declared Fn borrows immutably
5 => "five",
println!("Using blue as the background color");
Capturing env
while also testing that the value matched the range
with where syntax fn foo<T>(x: &[T]) where T: Debug { fn main() {
println!("Found an id in range: {}", id_variable) pattern
mutliple values 0 | 1 | 2 => "not many" },
let x = 4;
tuple with closures
The pattern code isn’t able to use the value from the
fn measure(measurement:(i32, u32))-> (i32, bool) Message::Hello { id: 10...12 } => {
id field, because we haven’t saved the id value in a
let equal_to_x = |z| z == x;
an enum Message::Quit => println!("Quit") println!("Found an id in another range") variable.
struct fn create(person: Person)-> Child
..for multiple trait bounds <T: Summarizable + Display> },
let y = 4;
a range 1 ... 5 => println!("got 1 to 5") Message::Hello { id } => {
In the last arm, where we’ve specified a variable But we haven’t applied any test to
assert!(equal_to_x(y));
println!("Found some other id: {}", id)
R u n p
without a range, we do have the value available to the value in the id field in this arm,
with where syntax fn some_function<T, U>(t: T, u: U) -> i32 },
} anything else _ => println!("something else")
}
use in the arm’s code in a variable named id. The
reason is that we’ve used the struct field shorthand
as we did with the first two arms:
any value would match this pattern
where T: Display + Clone, syntax. .
bou un
.map(|x| x + 1)
.filter(|x| x % 2 == 0)
{
Slice patterns fn foo(s: &[u8]) { println!("Some numbers: {}, {}", first, last);
},
} calculation: T,
slice patterns can match s {
}
Functions can be nested Functions are hoisted value: Option<u32>,
match on size of slice [a, b] => (),
}
[a, b, c] => (),
} _ => (),
}
}
H nd u
struct Viking {
do something
vikings.insert(Viking{name:"Olaf".to_string(), country:"Iceland".to_string()}, 13);
assign let f = File::open("hello.txt"); needs to be hashable
let dt = Utc.ymd(2017,7,8); //2014-07-08UTL
h Op on
name: String, Patterns that can fail to if let Some(x) = a_value
Rust explicates situations where
for (viking, health) in &vikings {
let f = match f { country: String, println!("{:?} has {} hp", viking, health); let dt = Utc.ymd(2014, 7, 8).and_hms(9, 10, 11); // `2014-07-08T09:10:11Z` match for some possible
w hm h
let some_u8_value = Some(0u8); let n = match opt{ }
}
value are refutable
Ok(file) => file,
value might not exist (be None)
num match some_u8_value { Some(x) => x, Err(error) => {
D od m
Function parameters, let statements, and for loops can only accept
->bool opt.is_none() opt.is_some() -> bool res.is_ok() res.is_err() G p o d Expressions evaluate to a resulting value
N wd w h h n d
opt.take() assert_eq!(x, None); option with value
Comb n n u
fn checked_sub_signed(self, rhs:
mapping Some(v) to Ok(v) and
opt.ok_or(err_val) let x = Some("foo"); dt1.signed_Duration_since(dt2) fn checked_add_signed(self, rhs:
OldDuration) ->
oop u
None to Err(err_val) OldDuration) ->
assert_eq!(x.ok_or(0), Ok("foo")); Option<Date<Tz>> Option<Date<Tz>>
order is arbitrary dt1 + Duration::seconds(num) -> dt
mapping Some(v) to Ok(v) and
None to Err(FnOnce())
opt.ok_or_else(FnOnce) let x: Option<&str> = None; -> duration::seconds
assert_eq!(x.ok_or(0), Err(0)); res1.and(res2) res2 if both Ok, else (first
encountered) error res.and_then(FnOnce) Calls fnOnce if the result is Err,
otherwise returns the Ok value of res
for key in map.keys() {.. ->&'a K
res1.or(res2) res2 if res1 is err,
dt.to_string(), "2014-11-28 12:00:09 UTC"
Comb n n op on
first_number_str.parse::<i32>().and_then(|first_number| {
else Ok val res1
second_number_str.parse::<i32>().map(|second_number| first_number * second_number)
res.or_else(FnOnce) Err value if err, }) for val in map.values() { ->&'a V "2014-11-28 12:00:09"
else calls F dt.format("%Y-%m-%d %H:%M:%S").to_string()
returns opt2 if opt1 and opt2 None if opt is None, else calls
opt1.and(opt2) are Some,else none opt.and_then(FnOnce) FnOnce with val in some
fn sq(x: u32) -> Result<u32, u32> { Ok(x * x) }
fn err(x: u32) -> Result<u32, u32> { Err(x) }
fn sq(x: u32) -> Result<u32, u32> { Ok(x * x) }
fn err(x: u32) -> Result<u32, u32> { Err(x) }
for val in map.values_mut() { ->&'a mut V
assert_eq!(Ok(2).or_else(sq).or_else(sq), Ok(2));
assert_eq!(Ok(2).and_then(sq).and_then(sq), Ok(16));
returns opt1 if some, Returns the option if it contains
opt1.or(opt2) else opt2 opt.or_else(FnOnce) a value, otherwise calls f and
assert_eq!(Ok(2).or_else(err).or_else(sq), Ok(2));
assert_eq!(Err(3).or_else(sq).or_else(err), Ok(9));
assert_eq!(Ok(2).and_then(sq).and_then(err), Err(4));
assert_eq!(Ok(2).and_then(err).and_then(sq), Err(2));
for (key, val) in map.iter() { for (key, val) in &map { ->(&'a K, &'a V)
returns the result.
assert_eq!(Err(3).or_else(err).or_else(err), Err(3)); assert_eq!(Err(3).and_then(sq).and_then(sq), Err(3));
->(&'a K, &'a mut V)
for (k, val) in map.iter_mut() {
e p ov des he o ow ng
Gener cs Tra ts #[der ve(tra t)] ter
A trait tells the Rust compiler about functionality a particular type has and
are abstract stand-ins for concrete operations for looping over, mapping, searching, filtering a
might share with other types
types or other properties collection of some sort, or something that yields items
D fin n
references, this leads to a possibly confusing situation where the
trait Iterator { struct Counter { impl Iterator for Counter {
•function (parameters, return type) Traits can be implemented for count: usize, type Item = usize; argument is a double reference. You can see this effect in the
wh ho d n
then provide its own custom behavior
A o d p
} can identify that the type in the angle brackets and can sometimes be surprising.
in Point is a generic type rather than a concrete iter and iter_mut are ad-hoc methods. This works around the context-
}
Adap e s Cyc es
type dependent bit and, by convention, let you obtain an iterator which will yield
impl Point<f32> { This code means the type Associated types are a way of associating a type using an associated type in stead of a generic, results in not #[derive(Default, Debug)]
it.iter_mut() which iterates over &mut T references
functions which take iterator
Repeats an iterator
Point<f32> will have a method
placeholder with a trait such that the trait having to specify the type when using a trait endlessly
fn distance_from_origin(&self) -> f32 { named distance_from_origin and struct SomeOptions {
and return other iterator
method definitions can use these placeholder
N m hod
(self.x.powi(2) + self.y.powi(2)).sqrt() other instances of Point<T> where T
is not of type f32 will not have this foo: i32,
rev a.iter().rev(); Reverses an reverse from cmp
} method defined
types in their signatures. map a.into_iter().map(|x| 2 * x) iterator's direction rev from iter
} When we use a trait, we have to provide type
bar: f32,
when a trait has a generic parameter, it can be implemented for
}
flat_map
let words = ["alpha", "beta", "gamma"];
skip a.iter().skip(2);
a type multiple times, changing the concrete types of the generic annotations to indicate which implementation let merged: String = words.iter()
counter.next() ->Option<item, None> .flat_map(|s| s.chars())
n num enum Option<T> { let integer = Some(5); type parameters each time. of the trait we want to use fn main() {
.collect();
assert_eq!(merged, "alphabetagamma"); skip_while a.into_iter().skip_while(|x| x.is_negative());
Some(T), let float = Some(5.0);
trait Graph<N, E> { fn distance<N, E, G: Graph<N, E>>(graph: &G, start: &N, end: &N) -> u32 { let options: SomeOptions = Default::default();
//thanks to default
None, let mut iter = a.into_iter() Because the closure passed to skip_while() takes a
o o
fn has_edge(&self, &N, &N) -> bool;
fn edges(&self, &N) -> Vec<E>; ... } println!("{:?}", options); //thanks to debug enumerate for (count, val) in a.iter().enumerate() reference, and many iterators iterate over references,
} .skip_while(|x| **x < 0); this leads to a possibly confusing situation, where the
// etc
} } chain let mut iter = a1.iter().chain(a2.iter()) // need two *s! type of the closure is a double reference:
collect
U n mu p n
let t: Vec<usize> = Counter::new().into_iter().collect() take a.iter().take(2);
Tra t bound
With associated types, we don’t need to fn distance<G: Graph>(graph: &G, start: &G::N, end: &G::N) -> u32 {
filter a.into_iter().filter(|x| x.is_positive())
annotate types because we can’t implement a ... }} limits use of a function to the Transforms an iterator
trait on a type multiple times into a collection let t= Counter::new().into_iter().collect<Vec<usize>>() take_while a.into_iter().take_while(|x| x.is_negative());
struct Point<T, U> { fn foo<A, B>(x: A, y: B) {.. types implementing the trait filter_map
let a = ["1", "lol", "3", "NaN", "5"];
removes option<t> layer
let mut iter = a.iter().filter_map(|s| s.parse().ok());
(when compared with filter
x: T, partition
trait Graph { struct Node;
assert_eq!(iter.next(), Some(1));
then map)
type N; struct Edge;
let (even, odd): (Vec<i32>, Vec<i32>) = assert_eq!(iter.next(), Some(3));
y: U, type E; struct MyGraph;
Consumes an assert_eq!(iter.next(), Some(5));
fn has_edge(&self, &Self::N, &Self::N) -> bool; impl Graph for MyGraph {
a.into_iter().partition(|&n|n%2==0)
n p
assert_eq!(iter.next(), None);
} T: Trait x: T impl Trait iterator, creating two a.iter()
fn edges(&self, &Self::N) -> Vec<Self::E>; type N = Node;
// etc type E = Edge; let mut iter = a.iter().map(|s| s.parse()).filter(|s| s.is_ok()).map(|s| s.unwrap());
collections from it. .cloned()
let p = Point { x: 5, y: 10.0 } fn(.....
}
or zip let a1 = [1, 2, 3]; for debugging .inspect(|x| println!("about to filter: {}", x))
.filter(|&x| x % 2 == 0)
let a2 = [4, 5, 6];
x: impl Trait let mut iter = a1.iter().zip(a2.iter()) .inspect(|x| println!("made it through filter: {}", x))
.fold(0, |sum, i| sum + i);
let a = [(1, 2), (3, 4)];
unzip
let (left,right):(Vec<_>,Vec<_>)= a.iter().cloned().unzip()
//left ==[1,3], right==[2,4]
G o m n D let path = Path::new("./foo/bar.txt"); Open a file in read-only mode let mut f = File::open("foo.txt") fs::read_to_string("address.txt") -> Result<String> to string format! format!("{},{}", val1, val2)
h u po mm n n u
let foo: SocketAddr = fs:: to stdout println! print! format!("The number is {}", 1); // => "The number is 1"
An iterator over the arguments of get entries https://doc.rust-lang.org/book/index.html
for argument in env::args() {...} a process, yielding a String value for entry read_dir Open a file in write-only mode let mut f = File::create("foo.txt")
read_to_string("address.txt")?.parse()?
Ru b mp
permissions bytes copied contents!!
if exist, will use std::fs::File; use std::fs::File;
to stream write! writeln! use std::io::Write;
n onm n overwrite
use std::io::prelude::*; use std::io::prelude::*; fs::create_dir("/some/dir")
>boo is_file
contents of file
let mut file = File::create("foo.txt")?;
file.write_all(b"Hello, world!")?;
let mut file = File::open("foo.txt")?;
let mut contents = String::new(); fs::create_dir_all("/some/dir") Recursively create a directory and all of its
let mut w = Vec::new();
write!(&mut w, "Hello {}!", "world"); https://doc.rust-lang.org/rust-by-example/index.html
get match env::var(key) {.. Result<String, VarError>
path.starts_with("/etc") file.read_to_string(&mut contents)?;
parent components if they are missing
OpenOp ons
current process.
fs::remove_file("a.txt") ..named or.. format!("{value}", value=4);// => "4"
D o n o h m p
poses the ability to configure how a
is_dir File is opened and what operations
use std::fs::OpenOptions;
D En y
intermingled
write
M d u n B down No
sets write access .append(true)
pub fn current_exe() -> < >
represents an entry inside of
on w Path::new("/etc").join("passwd")
a directory on the filesystem
append
This option, when true, means that writes will
append to a file instead of overwriting previous .open("foo.txt");
www.breakdown-notes.com
contents. Returns an iterator over the
pub fn home_dir() -> < > for entry in fs::read_dir(dir) entries within a directory
->option path.with_extension("txt") truncate If a file is successfully opened with this option set it
will truncate the file to 0 length if it already exists let file = OpenOptions::new() use std::fs;
match env::home_dir() { create This option indicates whether a new file will be
.read(true)
Some(path) => println!("{}", path.display()),
path.with_file_name("bar.txt") created if the file does not yet already exist.
for entry in fs::read_dir(".")? {
let dir = entry?;
create_new No file is allowed to exist at .write(true)
println!("{:?}", dir.path());
None => println!("Impossible to get your home dir!"), the target location
.create(true)
}
Path::new("tmp/foo.txt").file_name() open Opens a file at path with the }
options specified
.open("foo.txt");
dir.path() dir.file_name()
path.file_stem()
filename
without ext
dir.file_type()
path.extension()
np m hod dir.metadata() metadata.permissions()