SlideShare a Scribd company logo
An Introduction to Rust
Rust Roma - Meetup
May 10, 2017
Who I am
Claudio Capobianco
wbigger@gmail.com
@settevolte
Meanwhile… install Rust!
https://www.rust-lang.org
curl https://sh.rustup.rs -sSf | sh
Code of this presentation is available on:
https://github.com/wbigger/RustIntro
When and why I did meet Rust
Last September, within my startup.
We were looking for a replacement for C/C++ code for our
multi-platform software library for IoT.
We considered Rust, Go, and Swift.
Why a replacement for C/C++?
Not only verbosity and safety, but also:
- test were not straightforward
- dependences management was a nightmare
- in general, continuous integration was really difficult to
obtain
More problems to tackle...
Much of time spent on debugging.
Several languages mixed in the same project.
Often modern languages are easy to learn but stucks
when software become complex.
What is Rust
Sponsored by Mozilla Research
The 0.1 release was in January 2012
The 1.0.0 stable release was in May 2015, since then the
backward compatibility is guaranteed
Most programming language by StackOverflow survey:
third place in 2015, first place in 2016!
Rust goal
Ruby,
Javascript,
Python, ...C C++ Java
Control Safety
Rust goal
Rust
Ruby,
Javascript,
Python, ...C C++ Java
Control Safety
Just to mention a few:
and many others, look at https://www.rust-lang.org/en-US/friends.html
RUST is already in production!
Hello world!
fn main() {
// Print text to the console
println!("Hello World!");
}
Key concepts
Rust is born with the aim to balance control and security.
That is, in other words:
operate at low level with high-level constructs.
What safety means?
Problem with safety happens when we have a resource
that at the same time:
● has alias: more references to the resource
● is mutable: someone can modify the resource
That is (almost) the definition of data race.
What safety means?
Problem with safety happens when we have a resource
that at the same time:
● has alias: more references to the resource
● is mutable: someone can modify the resource
That is (almost) the definition of data race.
alias + mutable =
The Rust Way
Rust solution to achieve both control and safety is to push
as much as possible checks at compile time.
This is achieved mainly through the concepts of
● Ownership
● Borrowing
● Lifetimes
Ownership
Ownership
Ownership
Ownership
Green doesn’t own
the book anymore
and cannot use it
fn take(vec: Vec<i32>) {
//…
}
Ownership
fn give() {
let mut vec = Vec::new();
vec.push(1);
vec.push(2);
take(vec);
}
data
length
capacity
vec
fn take(vec: Vec<i32>) {
//…
}
Ownership
fn give() {
let mut vec = Vec::new();
vec.push(1);
vec.push(2);
take(vec);
}
data
length
capacity
[0]
[1]
vec
fn take(vec: Vec<i32>) {
//…
}
Ownership
fn give() {
let mut vec = Vec::new();
vec.push(1);
vec.push(2);
take(vec);
}
data
length
capacity
[0]
[1]
vec
data
length
capacity
vec
take ownership
fn take(vec: Vec<i32>) {
//…
}
Ownership
fn give() {
let mut vec = Vec::new();
vec.push(1);
vec.push(2);
take(vec);
}
data
length
capacity
[0]
[1]
vec
data
length
capacity
vec
fn take(vec: Vec<i32>) {
//…
}
Ownership
fn give() {
let mut vec = Vec::new();
vec.push(1);
vec.push(2);
take(vec);
}
data
length
capacity
vec
cannot be used
because data is
no longer
available
fn take(vec: Vec<i32>) {
//…
}
Ownership - error
fn give() {
let mut vec = Vec::new();
vec.push(1);
vec.push(2);
take(vec);
vec.push(3);
}
Borrowing
Borrowing with &T
one or more references to a resource
Borrowing with &T
read
read
read
&T
Borrowing with &T
Green can use its
book again
Borrowing with &mut T
exactly one mutable reference
Borrowing with &mut T
Borrowing with &mut T
&mut T
Borrowing with &mut T
&mut T
Borrowing with &mut T
Green can use its
book again
fn user(vec: &Vec<i32>) {
//…
}
Borrowing
fn lender() {
let mut vec = Vec::new();
vec.push(1);
vec.push(2);
user(&vec);
} data
length
capacity
vec
Borrowing
data
length
capacity
[0]
[1]
vec
fn user(vec: &Vec<i32>) {
//…
}
fn lender() {
let mut vec = Vec::new();
vec.push(1);
vec.push(2);
user(&vec);
}
Borrowing
data
length
capacity
[0]
[1]
vec
datavec
fn user(vec: &Vec<i32>) {
//…
}
fn lender() {
let mut vec = Vec::new();
vec.push(1);
vec.push(2);
user(&vec);
}
fn lender() {
let mut vec = Vec::new();
vec.push(1);
vec.push(2);
user(&vec);
}
fn user(vec: &Vec<i32>) {
//…
}
Borrowing
data
length
capacity
[0]
[1]
vec
datavec
shared ref to vec
loan out vec
fn lender() {
let mut vec = Vec::new();
vec.push(1);
vec.push(2);
user(&vec);
}
fn user(vec: &Vec<i32>) {
vec.push(3);
}
Borrowing
data
length
capacity
[0]
[1]
vec
datavec
what happens if I
try to modify it?
loan out vec
Borrowing - error
fn lender() {
let mut vec = Vec::new();
vec.push(1);
vec.push(2);
user(&vec);
}
fn user(vec: &Vec<i32>) {
vec.push(3);
}
Lifetimes
Lifetimes
Remember that the owner has always the ability to destroy
(deallocate) a resource!
In simplest cases, compiler recognize the problem and
refuse to compile.
In more complex scenarios compiler needs an hint.
Lifetimes
Lifetimes
&T
first borrowing
Lifetimes
&T
second
borrowing
!
Lifetimes
&T
dangling pointer!
Lifetime - first example
fn skip_prefix(line: &str, prefix: &str) -> &str {
let (s1,s2) = line.split_at(prefix.len());
s2
}
fn print_hello() {
let line = "lang:en=Hello World!";
let v;
{
let p = "lang:en=";
v = skip_prefix(line, p);
}
println!("{}", v);
}
Lifetime - first example
fn skip_prefix(line: &str, prefix: &str) -> &str {
let (s1,s2) = line.split_at(prefix.len());
s2
}
fn print_hello() {
let line = "lang:en=Hello World!";
let v;
{
let p = "lang:en=";
v = skip_prefix(line, p);
}
println!("{}", v);
}
fn skip_prefix(line: &str, prefix: &str) -> &str {
let (s1,s2) = line.split_at(prefix.len());
s2
}
fn print_hello() {
let line = "lang:en=Hello World!";
let v;
{
let p = "lang:en=";
v = skip_prefix(line, p);
}
println!("{}", v);
}
Lifetime - first example
first borrowing
second borrowing
(we return something that is
not ours)
fn skip_prefix(line: &str, prefix: &str) -> &str {
let (s1,s2) = line.split_at(prefix.len());
s2
}
fn print_hello() {
let line = "lang:en=Hello World!";
let v;
{
let p = "lang:en=";
v = skip_prefix(line, p);
}
println!("{}", v);
}
Lifetime - first example
first borrowing
second borrowing
(we return something that is
not ours)
we know that “s2” is valid as long
as “line” is valid, but compiler
doesn’t know
fn skip_prefix(line: &str, prefix: &str) -> &str {
let (s1,s2) = line.split_at(prefix.len());
s2
}
fn print_hello() {
let line = "lang:en=Hello World!";
let v;
{
let p = "lang:en=";
v = skip_prefix(line, p);
}
println!("{}", v);
}
Lifetime - first example
refuse to
compile
fn skip_prefix(line: &str, prefix: &str) -> &str {
let (s1,s2) = line.split_at(prefix.len());
s2
}
fn print_hello() {
let line = "lang:en=Hello World!";
let v;
{
let p = "lang:en=";
v = skip_prefix(line, p);
}
println!("{}", v);
}
Lifetime - first example
Lifetime - example reviewed
fn skip_prefix<'a>(line: &'a str, prefix: &str) -> &'a str {
let (s1,s2) = line.split_at(prefix.len());
s2
}
fn print_hello() {
let line = "lang:en=Hello World!";
let v;
{
let p = "lang:en=";
v = skip_prefix(line, p);
}
println!("{}", v);
}
Lifetime - example reviewed
fn skip_prefix<'a>(line: &'a str, prefix: &str) -> &'a str {
let (s1,s2) = line.split_at(prefix.len());
s2
}
fn print_hello() {
let line = "lang:en=Hello World!";
let v;
{
let p = "lang:en=";
v = skip_prefix(line, p);
}
println!("{}", v);
}
borrowing source is now
explicit, through the
lifetime parameter
Hello World!
Other key concepts
Lock data not code
The technique to lock data instead of code is widely used,
but generally is up to responsibility of developers.
“Lock data, not code” is enforced in Rust
Option type
null does not exist in Rust
Rust uses the Option type instead.
enum Option<T> {
None,
Some(T),
}
let x = Some(7);
let y = None;
Result type
exceptions do not exist in Rust
Rust uses Result type instead.
enum Result<T, E> {
Ok(T),
Err(E),
}
let x = Ok(7);
let y = Error(“Too bad”);
Credits
Youtube
The Rust Programming Language by Alex Crichton
SpeakerDeck
Hello, Rust! — An overview by Ivan Enderlin

More Related Content

Rust Intro @ Roma Rust meetup

  • 1. An Introduction to Rust Rust Roma - Meetup May 10, 2017
  • 2. Who I am Claudio Capobianco wbigger@gmail.com @settevolte
  • 3. Meanwhile… install Rust! https://www.rust-lang.org curl https://sh.rustup.rs -sSf | sh Code of this presentation is available on: https://github.com/wbigger/RustIntro
  • 4. When and why I did meet Rust Last September, within my startup. We were looking for a replacement for C/C++ code for our multi-platform software library for IoT. We considered Rust, Go, and Swift.
  • 5. Why a replacement for C/C++? Not only verbosity and safety, but also: - test were not straightforward - dependences management was a nightmare - in general, continuous integration was really difficult to obtain
  • 6. More problems to tackle... Much of time spent on debugging. Several languages mixed in the same project. Often modern languages are easy to learn but stucks when software become complex.
  • 7. What is Rust Sponsored by Mozilla Research The 0.1 release was in January 2012 The 1.0.0 stable release was in May 2015, since then the backward compatibility is guaranteed Most programming language by StackOverflow survey: third place in 2015, first place in 2016!
  • 10. Just to mention a few: and many others, look at https://www.rust-lang.org/en-US/friends.html RUST is already in production!
  • 11. Hello world! fn main() { // Print text to the console println!("Hello World!"); }
  • 12. Key concepts Rust is born with the aim to balance control and security. That is, in other words: operate at low level with high-level constructs.
  • 13. What safety means? Problem with safety happens when we have a resource that at the same time: ● has alias: more references to the resource ● is mutable: someone can modify the resource That is (almost) the definition of data race.
  • 14. What safety means? Problem with safety happens when we have a resource that at the same time: ● has alias: more references to the resource ● is mutable: someone can modify the resource That is (almost) the definition of data race. alias + mutable =
  • 15. The Rust Way Rust solution to achieve both control and safety is to push as much as possible checks at compile time. This is achieved mainly through the concepts of ● Ownership ● Borrowing ● Lifetimes
  • 19. Ownership Green doesn’t own the book anymore and cannot use it
  • 20. fn take(vec: Vec<i32>) { //… } Ownership fn give() { let mut vec = Vec::new(); vec.push(1); vec.push(2); take(vec); } data length capacity vec
  • 21. fn take(vec: Vec<i32>) { //… } Ownership fn give() { let mut vec = Vec::new(); vec.push(1); vec.push(2); take(vec); } data length capacity [0] [1] vec
  • 22. fn take(vec: Vec<i32>) { //… } Ownership fn give() { let mut vec = Vec::new(); vec.push(1); vec.push(2); take(vec); } data length capacity [0] [1] vec data length capacity vec take ownership
  • 23. fn take(vec: Vec<i32>) { //… } Ownership fn give() { let mut vec = Vec::new(); vec.push(1); vec.push(2); take(vec); } data length capacity [0] [1] vec data length capacity vec
  • 24. fn take(vec: Vec<i32>) { //… } Ownership fn give() { let mut vec = Vec::new(); vec.push(1); vec.push(2); take(vec); } data length capacity vec cannot be used because data is no longer available
  • 25. fn take(vec: Vec<i32>) { //… } Ownership - error fn give() { let mut vec = Vec::new(); vec.push(1); vec.push(2); take(vec); vec.push(3); }
  • 27. Borrowing with &T one or more references to a resource
  • 29. Borrowing with &T Green can use its book again
  • 30. Borrowing with &mut T exactly one mutable reference
  • 34. Borrowing with &mut T Green can use its book again
  • 35. fn user(vec: &Vec<i32>) { //… } Borrowing fn lender() { let mut vec = Vec::new(); vec.push(1); vec.push(2); user(&vec); } data length capacity vec
  • 36. Borrowing data length capacity [0] [1] vec fn user(vec: &Vec<i32>) { //… } fn lender() { let mut vec = Vec::new(); vec.push(1); vec.push(2); user(&vec); }
  • 37. Borrowing data length capacity [0] [1] vec datavec fn user(vec: &Vec<i32>) { //… } fn lender() { let mut vec = Vec::new(); vec.push(1); vec.push(2); user(&vec); }
  • 38. fn lender() { let mut vec = Vec::new(); vec.push(1); vec.push(2); user(&vec); } fn user(vec: &Vec<i32>) { //… } Borrowing data length capacity [0] [1] vec datavec shared ref to vec loan out vec
  • 39. fn lender() { let mut vec = Vec::new(); vec.push(1); vec.push(2); user(&vec); } fn user(vec: &Vec<i32>) { vec.push(3); } Borrowing data length capacity [0] [1] vec datavec what happens if I try to modify it? loan out vec
  • 40. Borrowing - error fn lender() { let mut vec = Vec::new(); vec.push(1); vec.push(2); user(&vec); } fn user(vec: &Vec<i32>) { vec.push(3); }
  • 42. Lifetimes Remember that the owner has always the ability to destroy (deallocate) a resource! In simplest cases, compiler recognize the problem and refuse to compile. In more complex scenarios compiler needs an hint.
  • 47. Lifetime - first example fn skip_prefix(line: &str, prefix: &str) -> &str { let (s1,s2) = line.split_at(prefix.len()); s2 } fn print_hello() { let line = "lang:en=Hello World!"; let v; { let p = "lang:en="; v = skip_prefix(line, p); } println!("{}", v); }
  • 48. Lifetime - first example fn skip_prefix(line: &str, prefix: &str) -> &str { let (s1,s2) = line.split_at(prefix.len()); s2 } fn print_hello() { let line = "lang:en=Hello World!"; let v; { let p = "lang:en="; v = skip_prefix(line, p); } println!("{}", v); }
  • 49. fn skip_prefix(line: &str, prefix: &str) -> &str { let (s1,s2) = line.split_at(prefix.len()); s2 } fn print_hello() { let line = "lang:en=Hello World!"; let v; { let p = "lang:en="; v = skip_prefix(line, p); } println!("{}", v); } Lifetime - first example first borrowing second borrowing (we return something that is not ours)
  • 50. fn skip_prefix(line: &str, prefix: &str) -> &str { let (s1,s2) = line.split_at(prefix.len()); s2 } fn print_hello() { let line = "lang:en=Hello World!"; let v; { let p = "lang:en="; v = skip_prefix(line, p); } println!("{}", v); } Lifetime - first example first borrowing second borrowing (we return something that is not ours) we know that “s2” is valid as long as “line” is valid, but compiler doesn’t know
  • 51. fn skip_prefix(line: &str, prefix: &str) -> &str { let (s1,s2) = line.split_at(prefix.len()); s2 } fn print_hello() { let line = "lang:en=Hello World!"; let v; { let p = "lang:en="; v = skip_prefix(line, p); } println!("{}", v); } Lifetime - first example refuse to compile
  • 52. fn skip_prefix(line: &str, prefix: &str) -> &str { let (s1,s2) = line.split_at(prefix.len()); s2 } fn print_hello() { let line = "lang:en=Hello World!"; let v; { let p = "lang:en="; v = skip_prefix(line, p); } println!("{}", v); } Lifetime - first example
  • 53. Lifetime - example reviewed fn skip_prefix<'a>(line: &'a str, prefix: &str) -> &'a str { let (s1,s2) = line.split_at(prefix.len()); s2 } fn print_hello() { let line = "lang:en=Hello World!"; let v; { let p = "lang:en="; v = skip_prefix(line, p); } println!("{}", v); }
  • 54. Lifetime - example reviewed fn skip_prefix<'a>(line: &'a str, prefix: &str) -> &'a str { let (s1,s2) = line.split_at(prefix.len()); s2 } fn print_hello() { let line = "lang:en=Hello World!"; let v; { let p = "lang:en="; v = skip_prefix(line, p); } println!("{}", v); } borrowing source is now explicit, through the lifetime parameter Hello World!
  • 56. Lock data not code The technique to lock data instead of code is widely used, but generally is up to responsibility of developers. “Lock data, not code” is enforced in Rust
  • 57. Option type null does not exist in Rust Rust uses the Option type instead. enum Option<T> { None, Some(T), } let x = Some(7); let y = None;
  • 58. Result type exceptions do not exist in Rust Rust uses Result type instead. enum Result<T, E> { Ok(T), Err(E), } let x = Ok(7); let y = Error(“Too bad”);
  • 59. Credits Youtube The Rust Programming Language by Alex Crichton SpeakerDeck Hello, Rust! — An overview by Ivan Enderlin