Professional Documents
Culture Documents
LGR Cheat Sheet
LGR Cheat Sheet
7
Table of Contents
YouTube Channel:https://www.youtube.com/c/LetsGetRusty
Basic Types & Variables Struct
/ Definition
/
bool- Boolean
struct
User
{
username:
String
,
nsigned integers
U
active:
bool,
u8,u16,u32,u64,u128
}
igned integers
S
/ Instantiation
/
i8,i16,i32,i64,i128
let
user1 = User {
username:
String
::from(
"bogdan"
),
loating point numbers
F
active:
true
,
f32,f64
};
et
l x =
5
;
if
counter ==
10{
let
x = x *
2
;
break
counter;
}
Type alias };
/ `NanoSecond` is a new name for `u64`.
/
type
NanoSecond
=
u64
;
while and while let
while
n <101
{
Control Flow n +=
1
;
}
if and if let
let
num =
Some
(
22
);
let
mut
optional =
Some
(
0
)
;
if
num.is_some() { while
letSome(i) = optional {
println!
(
"number is: {}"
, num.unwrap());
print!
(
"{}"
, i);
}
}
loop let
names =
vec!
[
"
Bogdan"
,
"Wallace"
];
et
l mut
count =
0;
loop
{ for
name
innames.iter() {
count +=
1
;
println!
(
"{}"
, name);
if
count ==
5
{ }
break
;
// Exit loop
}
match
}
let
optional =
Some
(
0
)
;
Borrowing fn
main
() {
let
x =
5;
Ownership rules takes_copy(x);
// x is copied by value
1. Each value in Rust has a variable that’s called its
owner. et
l s =
String
::from(
"Let’s Get Rusty!"
);
2. There can only be one owner at a time. // s is moved into the function
3. When the owner goes out of scope, the value will takes_ownership(s);
be dropped.
/ return value is moved into s1
/
Borrowing rules let
s1 = gives_ownership();
1. At any given time, you can haveeitherone
mutable referenceorany number of immutable et
l s2 =
String
::from(
"LGR"
);
references. let
s3 = takes_and_gives_back(s2);
2. References must always be valid. }
et
l mut
s2 =
String::from(
"hello"
);
fn
takes_ownership(some_string:
String
) {
let
s2_ref = &
mut
s2;// mutable reference println!
(
"{}"
, some_string);
}
// some_string goes out of scope and drop
s2_ref.push_str(
" world!"
);
is called. The backing memory is freed.
fn
gives_ownership
() ->
String
{
Copy, Move, and Clone let
some_string =
String
::from(
"LGR"
);
/ Simple values which implement the Copy
/ some_string
trait are copied by value
}
let
x =
5
;
let
y = x; n
f takes_and_gives_back
(some_string:
String
) ->
String
{
println!
(
"{}"
, x);
// x is still valid some_string
}
/ The string is moved to s2 and s1 is
/
invalidated
let
s1 =
String
::from(
"Let's Get Rusty!"
);
let
s2 = s1;
// Shallow copy a.k.a move
println!
(
"{}"
, s1);
// Error: s1 is invalid
et
l s1 =
String
::from(
"Let's Get Rusty!"
);
let
s2 = s1.clone();
// Deep copy
match
x { match
version {
// matching literals
SemVer(major, _, _) => {
1
=>
println!
(
"one"
),
println!
(
"
{}"
, major);
// matching multiple patterns
}
2
|
3
=>
println!
(
"two or three"
),
}
// matching ranges
4
..=
9
=>
println!
(
"within range"
),
let
numbers = (
2
,
4
,
8,
16
,
32
);
// matching named variables
x =>
println!
(
"{}"
, x),
match
numbers {
// default case (ignores value)
(first, .., last) => {
_ =>
println!
(
"default Case"
)
println!
(
"
{}, {}"
, first, last);
}
}
}
Destructuring
struct
Point
{ Match guards
x:
i32
,
let
num =
Some
(
4
)
;
y:
i32
,
}
match
num {
Some
(x)
if
x <
5
=>println!
(
"
less than
let
p = Point { x:
0
,
y:
7
}; five: {}"
, x),
Some
(x) =>
println!
(
"{}"
, x),
match
p { None
=> (),
Point { x, y:
0
} => { }
println!
(
"{}"
, x);
},
@ bindings
Point { x, y } => {
println!
(
"{} {}"
, x, y); struct
User
{
},
id:
i32
}
}
enum
Shape
{ let
user = User { id:
5
};
Rectangle { width:
i32
, height:
i32
},
Circle(
i32
),
match
user {
}
User {
id: id_variable @
3
.
.=7
,
let
shape = Shape::Circle(
10
);
} =>
println!
(
"
id: {}", id_variable),
User { id:
10
..=
12
} => {
match
shape { println!
(
"
within range" );
Shape::Rectangle { x, y } =>
//... },
Shape::Circle(radius) =>
//... User { id } =>
println!(
"id: {}"
, id),
}
}
Iterators Error Handling
Usage Throw unrecoverable error
/ Methods that consume iterators
/ panic!
(
"Critical error! Exiting!"
);
let
v1 =
vec!
[
1
,
2
,
3];
let
v1_iter = v1.iter(); Option enum
let
total:
i32
= v1_iter.sum();
fn
get_user_id(name: &
str
) ->
Option
<
u
32
> {
/ Methods that produce new iterators
/ if
database.user_exists(name) {
let
v1:
Vec
<
i32
> =
vec!
[
1
,
2
,
3];
return
Some
(database.get_id(name))
let
iter = v1.iter().map(|x| x + 1
)
; }
impl
Counter { Err
(Error { msg:
"not logged in"
})
fn
new
() -> Counter {
}
Counter { count:
0
}
}
? operator
}
n
f get_salary(db: Database, id:
i32
) ->
Option
<
u32
> {
impl
Iterator
for
Counter {
Some
(db.get_user(id)?.get_job()?.salary)
type
Item
=
u32
;
}
n
f next
(&
mut
self
) ->
Option
<Self::Item>
n
f connect
(db: Database) ->
{
Result
<Connection, Error> {
if
self
.count <
5{
let
conn =
self
.count +=
1;
db.get_active_instance()?.connect()?;
Some
(
self
.count)
Ok
(conn)
}
else
{
}
None
}
}
}
Combinators Boxing errors
.map use
std::error;
let
some_string =
Some
(
"LGR"
.to_owned());
ype
t Result
<T> = std::result::
Result
<T,
Box
<dyn error::Error>>;
et
l some_len = some_string.map(|s|
s.len());
Iterating over errors
truct
s Error
{ msg:
String
} Ignore failed items with filter_map()
struct
User
{ name:
String
}
et
l strings =vec!
[
"
LGR"
,
"22",
"7"
];
let
numbers:
Vec<_> = strings
et
l string_result:
Result<
S
tring
, Error> =
.into_iter()
Ok
(
"Bogdan"
.to_owned());
.filter_map(|s| s.parse::<
i32
>().ok())
.collect();
let
user_result:
Result
<User, Error> =
string_result.map(|name| {
User { name }
Fail the entire operation with collect()
});
let
strings =
vec!
[
"
LGR"
,
"22"
,
"7"
];
.and_then let
numbers:
Result
<
V
ec
<_>, _> = strings
.into_iter()
et
l vec =
Some
(
vec!
[
1
,
2
,
3]);
.map(|s| s.parse::<
i32
>())
let
first_element = vec.and_then(
.collect();
|vec| vec.into_iter().next()
);
Collect all valid values and failures with partition()
et
l string_result:
Result
<&
'static
str
, _>
let
strings =
vec!
[
"
LGR"
,
"22"
,
"7"
];
=
Ok
(
"
5"
);
let
number_result = et
l (numbers, errors): (
Vec
<_>,
Vec
<_>) =
string_result
strings
.and_then(|s| s.parse::<
u32
>());
.into_iter()
.map(|s| s.parse::<
i32
>())
Multiple error types .partition(
Result
::is_ok);
fn
add
(
self
, other: Point) -> Point {
Default implementations with Derive Point {
/ A tuple struct that can be printed
/ x:
self
.x + other.x,
#[derive(Debug)]
y:
self
.y + other.y,
struct
Inches
(
i
32);
}
}
}
Supertraits Function pointers
use
std::fmt; n
f do_twice
(f:
fn
(
i32
) ->
i32
, arg:
i32
) ->
i32
{
trait
Log
: fmt::Display {
f(arg) + f(arg)
fn
log
(&
self
) {
}
let
output =
self
.to_string();
println!
(
"Logging: {}"
, output);
Creating closures
}
}
let
add_one = |num:
u32
| ->
u32
{
num +
1
};
Lifetimes in function signatures
n
f longest<
'a
>(x: &
'a
str, y: &
'a
str
) ->
Returning closures
&
'a
str
{
if
x.len() > y.len() { fn
add_one
() ->
impl
Fn
(
i
32
) ->
i32
{
x
|x| x +
1
}
else
{ }
y
}
n
f add_or_subtract (x:
i32
) ->
Box
<dyn
}
Fn
(
i32
) ->
i32> {
if
x >10
{
Box
::new(
move
|y| y + x)
Lifetimes in struct definitions }
else {
struct
User
<
'a
> {
Box
::new(
move
|y| y - x)
full_name: &
'a
str
,
}
}
}
Raw pointers
Creating a new package with a library crate
et
l mut
num =
5
;
$ cargo new my-project --lib
// immutable raw pointer
let
r1 = &num
as*
c
onst
i32;
// mutable raw pointer
Defining and using modules
let
r2 = &
mut
numas
*
m
ut
i32;
fn
some_function
() {}
pub
use
crate::outer_module::inner_module;