Presentations
ptisnovs@redhat.com
(D, Nimrod, …)
gofmt
Language Rust Go
Approach modern conservative
Syntax complicated simple, minimalistic
Learning curve lower slope higher slove
Learning curve higher maximum lower maximum
Compiler speed slower faster
Backend LLVM custom
Linking static/dynamic via -buildmode (//export!!!)
Code speed faster slower
Type system huge without generics (yet)
Immutability explicit string, other via interfaces
Memory management ownership GC
Race condition c. yes not direcly
Dependency mngm. cargo Go modules
error[E0382]: use of moved value: `c`
--> an_example.rs:40:8
|
39 | funkce1(c);
| - value moved here
40 | funkce2(c);
| ^ value used here after move
|
= note: move occurs because `c` has type `std::rc::Rc<Complex>`, which does not implement the `Copy` trait
fn foo(a int32) {
println!(a)
}
fn main() {
let x:i32 = 10
foo(x);
}
i8
, u128
etc.// macro println!
fn main() {
let x = 6;
let y = 7;
let z;
// now compiler knows types of all variables
z = x * y;
println!("{} * {} = {}", x, y, z);
}
Option
null
or nil
usage
Result
data typeSome
valueNone
fn div(x: i32, y: i32) -> Option<i32> {
if y != 0 {
Some(x / y)
} else {
None
}
}
fn main() {
let z1 = div(2, 1);
println!("{:?}", z1);
let z2 = div(2, 0);
println!("{:?}", z2);
}
Result
null
or nil
usage, or special error values
Option
data typeOk
valueErr
error valuefn div(x: i32, y: i32) -> Result<i32, &'static str> {
if y != 0 {
Ok(x / y)
} else {
Err("Divide by zero!")
}
}
fn main() {
let z1 = div(2, 1);
println!("{:?}", z1);
let z2 = div(2, 0);
println!("{:?}", z2);
}
Result
and pattern matchingfn div(x: i32, y: i32) -> Result<i32, &'static str> {
if y != 0 {
Ok(x / y)
} else {
Err("Divide by zero!")
}
}
fn print_div_result(result: Result<i32, &'static str>) {
match result {
Ok(value) => println!("value: {}", value),
Err(error) => println!("error: {}", error),
}
}
fn main() {
let z1 = div(2, 1);
print_div_result(z1);
let z2 = div(2, 0);
print_div_result(z2);
}
Result
in computationfn div(x: i32, y: i32) -> Result<i32, &'static str> {
if y != 0 {
Ok(x / y)
} else {
Err("Divide by zero!")
}
}
fn print_div_result(result: Result<i32, &'static str>) {
match result {
Ok(value) => println!("value: {}", value),
Err(error) => println!("error: {}", error),
}
}
fn inc(x: i32) -> i32 {
x + 1
}
fn main() {
let z0 = div(0, 1);
print_div_result(z0);
print_div_result(z0.map(inc));
let z2 = div(2, 0);
print_div_result(z2);
print_div_result(z2.map(inc));
}
fn main() {
let is_odd = |x: i32| x & 1 == 1;
//let is_even = |x: i32| !is_odd(x);
let square = |x: i32| x*x;
for x in 0..10 {
println!("{}*{}={}, {} is {} number",
x, x, square(x), x, if is_odd(x) {"odd"} else {"even"})
}
}
fn main() {
let is_odd = |x: i32| x & 1 == 1;
//let is_even = |x: i32| !is_odd(x);
let square = |x: i32| x*x;
for x in 0..10 {
println!("{}*{}={}, {} is {} number",
x, x, square(x), x, if is_odd(x) {"odd"} else {"even"})
}
}
mut
range
)map
filter
take
take_while
fold
fn main() {
for n in 1..10 {
let fact = (1..n + 1).fold(1, |prod, x| prod * x);
println!("{}! = {}", n, fact);
}
}
fn main() {
let iter1 = 1..;
let iter2 = iter1.filter(|x| x % 2 == 0);
let iter3 = iter2.take(10);
let suma = iter3.fold(0, |sum, x| sum + x);
println!("sum = {}", suma);
}
// matching (simplest variant)
fn main() {
let x: i32 = 1;
match x {
0 => println!("zero"),
1 => println!("one"),
2 => println!("two"),
3 => println!("three"),
_ => println!("something else"),
}
}
// matching, more complicated
fn classify(x:i32) -> &'static str {
match x {
0 => "zero",
1 | 2 => "one or two",
3 | 4 | 5 => "from three to five",
10 ... 20 => "from ten to twenty",
_ => "something else",
}
}
fn main() {
for x in 0..10 {
println!("{}:{}", x, classify(x))
}
}
NULL
/nil
fn main() {
let x = Box::new(42);
println!("{}", x);
}
let c = Box::new(Complex::new(1.0, 2.0));
// deref
fn print_complex(c: Box<Complex>) {
println!("Complex number: {:}+{:}i", c.real, c.imag);
}
Rc::clone()
Deref
trait)fn main() {
println!("main begin");
let c = Rc::new(Complex::new(0.0, 0.0));
c.print();
{
println!("inner block begin");
let c2 = Rc::new(Complex::new(0.0, 0.0));
c2.print();
{
println!("inmost block begin");
let c3 = Rc::new(Complex::new(0.0, 0.0));
c3.print();
println!("inmost block end");
}
println!("inner block end");
}
println!("main end");
}
// one object that is shared three times
fn main() {
println!("main begin");
let c = Rc::new(Complex::new(0.0, 0.0));
c.print();
{
println!("inner block begin");
let c2 = c.clone();
c2.print();
{
println!("inmost block begin");
let c3 = c.clone();
c3.print();
println!("inmost block end");
}
println!("inner block end");
}
println!("main end");
}
Arc::clone()
Deref
traitfn start_threads() {
let c = Arc::new(Complex::new(1.0, 1.0));
for id in 0..10 {
let owner = ComplexNumberOwner { id: id, value: c.clone() };
// move semantic
// because object can live longer than current thread
thread::spawn(move || {
owner.print();
delay(400);
});
}
}
fn main() {
// first type of array constructor
let array = [10, 20, 30, 40];
// array length in runtime
println!("array has {} items", array.len());
// range construct + array length
for i in 0..array.len() {
println!("item #{} = {}", i + 1, array[i]);
}
// for-each loop over array
for i in array.iter() {
println!("{}", i);
}
}
fn main() {
// second type of array constructor
let array = [1; 10];
// array length in runtime
println!("array has {} items", array.len());
// range construct + array length
for i in 0..array.len() {
println!("item #{} = {}", i + 1, array[i]);
}
// for-each loop over array
for i in array.iter() {
println!("{}", i);
}
}
vec!
macrofn main() {
// vector construction using macro
let vector = vec![1, 2, 3, 4, 5];
// vector length in runtime
println!("vector has {} items", vector.len());
// range construct + vector length
for i in 0..vector.len() {
println!("item #{} = {}", i + 1, vector[i]);
}
// for-each loop over vector
for item in vector.iter() {
println!("{}", item);
}
// this is even shorter
for item in &vector {
println!("{}", item);
}
}
fn main() {
// array constructor
let array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
// slice constructor
let array2 = &array[2..6];
// iteration over slice
for i in array2.iter() {
println!("{}", i);
}
}
fn main() {
// array constructor
let array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
// slice constructor
let array2 = &array[5..];
// iteration over slice
for i in array2.iter() {
println!("{}", i);
}
}
fn main() {
// vector constructor
let vector = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
println!("vector has {} items", vector.len());
// slice constructor
let slice = &vector[3..7];
println!("slice has {} items", slice.len());
}
use std::thread;
fn main() {
println!("Starting");
for i in 1..10 {
thread::spawn(move || {
println!("Hello from a thread #{}", i);
});
}
println!("Stopping");
}
cargo test
#[test]
fn ok_test() {
}
#[test]
fn failure() {
assert!(false);
}
mockiato
- mockingmockito
- HTTP mockingrust-fuzz/afl.rs
- fuzzer based on the great AFL tool