CopyrightPrismTech,2017
Angelo	Corsaro,	PhD
CTO,	ADLINK	Tech.	Inc.	
Co-Chair,	OMG	DDS-SIG	
angelo.corsaro@adlinktech.com
RUSTing
Partially Ordered
Rust Programming Ruminations
CopyrightPrismTech,2017
RUSTing is not a tutorial on the Rust programming
language.
I decided to create the RUSTing series as a way to
document and share programming idioms and techniques.
From time to time I’ll draw parallels with Haskell and Scala,
having some familiarity with one of them is useful but not
indispensable.
Prologue
CopyrightPrismTech,2017
Rust is a system programming
language that provides zero
cost high-level abstractions
and language-enforced
memory and concurrency
safety.
What is Rust?
CopyrightPrismTech,2017
Installing Rust is simple, just do*:
Getting Started
$ curl https://sh.rustup.rs -sSf | sh
I suggest you also install the documentation locally:
$ rustup component add rust-docs
Open the doc with:
$ rustup doc
CopyrightPrismTech,2017
Working with Monads…
CopyrightPrismTech,2017
The first monad one typically encounter is a List, but the
second one is usually the Maybe Monad
Like Scala, and differently from Haskell, Rust has named
the Monad used to model the “potential” presence of a
value as std::option::Option
Maybe is an Option
CopyrightPrismTech,2017
The Option Monad is an algebraic
data type with two variants,
Some(T) and None
The derive directives injects a
series of traits
The rest of the monad is
implemented in the impl clause
(see here)
The Option Monad
#[derive(Clone, Copy, PartialEq,
PartialOrd, Eq, Ord,
Debug, Hash)]
pub enum Option<T> {
None,
Some(T),
}
CopyrightPrismTech,2017
Depending on your background you may be familiar with at least
three ways of working with Option, and with Monad in generals
- map/flatMap
- map :: (a -> b) -> M a -> M b
- flatMap :: (a -> M b) -> M a -> M b
- Pattern Matching
- do construct in Haskell / for construct in Scala
Let’s investigate what the equivalents are in Rust
Working with an Option
CopyrightPrismTech,2017
Hardcore functional programmers live out of
map and flatMap
Rust’s Option type is equipped with a map
defined as:
In Rust’s , flatMap called and_then, is defined as:
The Orthodox Option
fn and_then<U, F>(self, f: F) -> Option<U>
where F: FnOnce(T) -> Option<U>
fn map<U, F>(self, f: F) -> Option<U>
where F: FnOnce(T) -> U
CopyrightPrismTech,2017
As a result the orthodox way of dealing with
options is to use map and and_then:
The Orthodox Option
let a = Some(18);
let b = Some(24);
let c = a.and_then(|x| {
b.map(|y| { x + y })
});
println!("{:?} + {:?} = {:?}", a, b, c);
[rust]: Some(18) + Some(24) = Some(42)
CopyrightPrismTech,2017
Another way to work with the Option type is
to use pattern matching as shown below:
Pattern Matching Option
let a = Some(18);
let b = Some(24);
let c = match a {
Some(x) => match b {
Some(y) => Some(x+y),
None => None
},
None => None
};
println!("{:?} + {:?} = {:?}", a, b, c);
[rust]: Some(18) + Some(24) = Some(42)
CopyrightPrismTech,2017
That was easy. Let’s try with strings…
Ownership and Moves
let s = Some(String::from(“Welcome to"));
let t = Some(String::from("Rust!"));
let u = s.and_then(|a| {
t.map(|b| { format!("{} {}", a, b).to_string()})
});
println!("{:?} + {:?} = {:?}", s, t, u);
[…]
error[E0382]: use of moved value: `s`
error[E0382]: use of moved value: `t`
CopyrightPrismTech,2017
The reason why the apparently innocent example does not
compile has to do with Rust Ownership and Move semantics.
Ownership and Moves
let s = Some(String::from(“Welcome to"));
let t = Some(String::from("Rust!"));
let u = s.and_then(|a| {
t.map(|b| { format!("{} {}", a, b).to_string()})
});
println!("{:?} + {:?} = {:?}", s, t, u);
The moved t is freed here
The moved s is freed here
CopyrightPrismTech,2017
To avoid moving the value held by the option into the
lambda we have to use as_ref
Ownership and Moves
let s = Some(String::from(“Welcome to"));
let t = Some(String::from("Rust!"));
let u = s.as_ref().and_then(|a| {
t.as_ref().map(|b| { format!("{} {}", a, b).to_string()})
});
println!("{:?} + {:?} = {:?}", s, t, u);
[…]
[rust]: Some(“Welcome to") + Some("Rust!") = Some("Welcome to Rust!")
CopyrightPrismTech,2017
You have to watch out for moves also when using pattern
matching. As a consequence the following snippet also
suffers from “unintended” move
Move & Pattern Matching
let s = Some(String::from(“Welcome to"));
let t = Some(String::from(“Rust!"));
let u = match s {
Some(a) => match t {
Some(b) => Some(format!("{} {}", a, b)),
None => None
},
None => None
};
println!("{:?} + {:?} = {:?}", s, t, u);
The moved s is freed here
The moved t is freed here
CopyrightPrismTech,2017
As we’ve seen with and_then/map the trick is to use
references. Please notice that as Option implements the
Copy trait we need to use the reference only on its
content — otherwise we would have had to match by &
Move & Pattern Matching
let s = Some(String::from(“Welcome to"));
let t = Some(String::from(“Rust!"));
let u = match s {
Some(ref a) => match t {
Some(ref b) => Some(format!("{} {}", a, b)),
None => None
},
None => None
};
println!("{:?} + {:?} = {:?}", s, t, u);
CopyrightPrismTech,2017
If you are fond of Haskell’s do or Scala’s for construct
you can achieve a similar syntactical sugar by using
Rust’s iterators
Iterating an Option
let s = Some(String::from(“Welcome to"));
let t = Some(String::from(“Rust!"));
let mut u = None;
for a in s.iter() {
for b in t.iter() {
u = Some(format!("{} {}", a, b))
}
}
println!("{:?} + {:?} = {:?}", s, t, u);
This is not my favourite way
as I don’t like to use
mutability so casually.
It’d be much nicer if the
for-loop would allow to
return a value
[…]
[rust]: Some(“Welcome to") + Some("Rust!") = Some("Welcome to Rust!")

RUSTing -- Partially Ordered Rust Programming Ruminations

  • 1.
  • 2.
    CopyrightPrismTech,2017 RUSTing is nota tutorial on the Rust programming language. I decided to create the RUSTing series as a way to document and share programming idioms and techniques. From time to time I’ll draw parallels with Haskell and Scala, having some familiarity with one of them is useful but not indispensable. Prologue
  • 3.
    CopyrightPrismTech,2017 Rust is asystem programming language that provides zero cost high-level abstractions and language-enforced memory and concurrency safety. What is Rust?
  • 4.
    CopyrightPrismTech,2017 Installing Rust issimple, just do*: Getting Started $ curl https://sh.rustup.rs -sSf | sh I suggest you also install the documentation locally: $ rustup component add rust-docs Open the doc with: $ rustup doc
  • 5.
  • 6.
    CopyrightPrismTech,2017 The first monadone typically encounter is a List, but the second one is usually the Maybe Monad Like Scala, and differently from Haskell, Rust has named the Monad used to model the “potential” presence of a value as std::option::Option Maybe is an Option
  • 7.
    CopyrightPrismTech,2017 The Option Monadis an algebraic data type with two variants, Some(T) and None The derive directives injects a series of traits The rest of the monad is implemented in the impl clause (see here) The Option Monad #[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Debug, Hash)] pub enum Option<T> { None, Some(T), }
  • 8.
    CopyrightPrismTech,2017 Depending on yourbackground you may be familiar with at least three ways of working with Option, and with Monad in generals - map/flatMap - map :: (a -> b) -> M a -> M b - flatMap :: (a -> M b) -> M a -> M b - Pattern Matching - do construct in Haskell / for construct in Scala Let’s investigate what the equivalents are in Rust Working with an Option
  • 9.
    CopyrightPrismTech,2017 Hardcore functional programmerslive out of map and flatMap Rust’s Option type is equipped with a map defined as: In Rust’s , flatMap called and_then, is defined as: The Orthodox Option fn and_then<U, F>(self, f: F) -> Option<U> where F: FnOnce(T) -> Option<U> fn map<U, F>(self, f: F) -> Option<U> where F: FnOnce(T) -> U
  • 10.
    CopyrightPrismTech,2017 As a resultthe orthodox way of dealing with options is to use map and and_then: The Orthodox Option let a = Some(18); let b = Some(24); let c = a.and_then(|x| { b.map(|y| { x + y }) }); println!("{:?} + {:?} = {:?}", a, b, c); [rust]: Some(18) + Some(24) = Some(42)
  • 11.
    CopyrightPrismTech,2017 Another way towork with the Option type is to use pattern matching as shown below: Pattern Matching Option let a = Some(18); let b = Some(24); let c = match a { Some(x) => match b { Some(y) => Some(x+y), None => None }, None => None }; println!("{:?} + {:?} = {:?}", a, b, c); [rust]: Some(18) + Some(24) = Some(42)
  • 12.
    CopyrightPrismTech,2017 That was easy.Let’s try with strings… Ownership and Moves let s = Some(String::from(“Welcome to")); let t = Some(String::from("Rust!")); let u = s.and_then(|a| { t.map(|b| { format!("{} {}", a, b).to_string()}) }); println!("{:?} + {:?} = {:?}", s, t, u); […] error[E0382]: use of moved value: `s` error[E0382]: use of moved value: `t`
  • 13.
    CopyrightPrismTech,2017 The reason whythe apparently innocent example does not compile has to do with Rust Ownership and Move semantics. Ownership and Moves let s = Some(String::from(“Welcome to")); let t = Some(String::from("Rust!")); let u = s.and_then(|a| { t.map(|b| { format!("{} {}", a, b).to_string()}) }); println!("{:?} + {:?} = {:?}", s, t, u); The moved t is freed here The moved s is freed here
  • 14.
    CopyrightPrismTech,2017 To avoid movingthe value held by the option into the lambda we have to use as_ref Ownership and Moves let s = Some(String::from(“Welcome to")); let t = Some(String::from("Rust!")); let u = s.as_ref().and_then(|a| { t.as_ref().map(|b| { format!("{} {}", a, b).to_string()}) }); println!("{:?} + {:?} = {:?}", s, t, u); […] [rust]: Some(“Welcome to") + Some("Rust!") = Some("Welcome to Rust!")
  • 15.
    CopyrightPrismTech,2017 You have towatch out for moves also when using pattern matching. As a consequence the following snippet also suffers from “unintended” move Move & Pattern Matching let s = Some(String::from(“Welcome to")); let t = Some(String::from(“Rust!")); let u = match s { Some(a) => match t { Some(b) => Some(format!("{} {}", a, b)), None => None }, None => None }; println!("{:?} + {:?} = {:?}", s, t, u); The moved s is freed here The moved t is freed here
  • 16.
    CopyrightPrismTech,2017 As we’ve seenwith and_then/map the trick is to use references. Please notice that as Option implements the Copy trait we need to use the reference only on its content — otherwise we would have had to match by & Move & Pattern Matching let s = Some(String::from(“Welcome to")); let t = Some(String::from(“Rust!")); let u = match s { Some(ref a) => match t { Some(ref b) => Some(format!("{} {}", a, b)), None => None }, None => None }; println!("{:?} + {:?} = {:?}", s, t, u);
  • 17.
    CopyrightPrismTech,2017 If you arefond of Haskell’s do or Scala’s for construct you can achieve a similar syntactical sugar by using Rust’s iterators Iterating an Option let s = Some(String::from(“Welcome to")); let t = Some(String::from(“Rust!")); let mut u = None; for a in s.iter() { for b in t.iter() { u = Some(format!("{} {}", a, b)) } } println!("{:?} + {:?} = {:?}", s, t, u); This is not my favourite way as I don’t like to use mutability so casually. It’d be much nicer if the for-loop would allow to return a value […] [rust]: Some(“Welcome to") + Some("Rust!") = Some("Welcome to Rust!")