Rust — это современный, практический, быстрый и безопасный язык программирования. Некоторые говорят, что Rust — это как C++, если бы его писал человек, знающий Haskell.
Система типов Rust решает главную проблему C++ — небезопасность. C++ очень легко сделать ошибки, которые приведут к поломкам (например, use after free). Rust позволяет писать безопасный код, сохраняя при этом выразительность и околонулевые накладные расходы C++. В докладе будут подробно описаны механизмы языка, которые контролируют безопасность программы.
Хотя в данный момент Rust ещё не подходит для использования в продакшне, его всё равно стоит изучать. Во-первых, потому что это очень интересный подход к программированию, а во-вторых, потому что через несколько лет для разработки требовательных к ресурсам программ будет необходим именно Rust или другой похожий инструмент.
11. // C++ llvm::ArrayRef<T>; Rust &[T]
struct Slice<T> {
T* begin;
T* end;
}
!
// C++ string_view; Rust: &str
type StrSlice = Slice<char>;
What is Slice
12. // similar to std::vector
let v1: Vec<uint> = vec!(10, 20, 30);
!
// Slice, similar to std::array_view
let v2: &[uint] = v1.as_slice();
!
// another slice
let v3 = v2.slice_from(1);
!
// prints [20, 30]
println!("{}", v3.to_str());
Vec
13. fn sum<T>(ns: &[T]) -> T {
let sum = T::zero();
for n in ns { sum += n; }
n
}
!
fn sum<T : Num>(ns: &[T]) -> T { … }
!
sum(&[1, 2]); // <- OK
sum(&[true, false]); // <- error is here
traits (type classes; concepts)
23. fn longest_str<'s>(a: &'s str, b: &'s str)
-> &'s str
{
if a.len() > b.len() { a } else { b }
}
!
fn foo<'a>(a: &'a str) -> &'a str {
let b = "bb".to_string();
// lifetime of c is intersection
let c = longest_str(
a.as_slice(), b.as_slice());
return c;
}
Lifetime intersection
24. void foo(vector<int>& xs) {
typedef vector<int>::iterator iter;
for (iter i = xs.begin(); i != xs.end(); ++i)
{
if (*i == 0) {
xs.push_back(1);
}
}
}
Mutability: C++
25.
26. fn foo(xs: &mut Vec<int>) {
for p in xs.iter() {
if *p == 0 {
xs.push(1);
}
}
}
Mutability: Rust
27.
28. let mut a = 1;
let b = &mut a;
let c = &mut a;
!
tmp2.rs:4:18: 4:19 error: cannot borrow `a` as
mutable more than once at a time
tmp2.rs:4 let c = &mut a;
^
tmp2.rs:3:18: 3:19 note: previous borrow of `a`
occurs here; the mutable borrow prevents subsequent
moves, borrows, or modification of `a` until the
borrow ends
tmp2.rs:3 let b = &mut a;
^
tmp2.rs:5:2: 5:2 note: previous borrow ends here
Cannot borrow as mutable twice
29. let mut a = 1;
a = 2;
let b = &a;
a = 3;
!
!
mut.rs:5:5: 5:6 error: cannot assign to `a`
because it is borrowed
mut.rs:5 a = 3;
^
mut.rs:4:13: 4:15 note: borrow of `a` occurs here
mut.rs:4 let b = &a;
^~
Cannot assign, because borrowed
34. for i in range(0, 100) {
// proc is a keyword
// proc closure can be passed btw threads
// and may be called no more than once
task::spawn(proc() {
println!("{}", i);
});
}
Tasks
35. let (sender, receiver) = channel();
!
for i in range(0, 100) {
let sender_for_task = sender.clone();
task::spawn(proc() {
// do something
sender_for_task.send(i * i);
});
}
!
for i in range(0, 100) {
let r = receiver.recv();
println!("{}", r);
}
Channels
36. // similar to Rc<T> except
// Arc uses atomic counter, not plain
// data is immutable inside Arc
// so Arc can be safely shared between threads
let conf = Arc::new(ServerConf { … });
!
for i in range(0, 100) {
// must get a copy of Arc
// to pass it to another thread
let conf_c = conf.clone();
task::spawn(proc() {
println!("{}", conf_c);
});
}
Arc<T>
38. fn do_smth(shared_data: Arc<Mutex<T>>) {
// guard + smart pointer
let ptr_and_lock = shared_data.lock();
ptr_and_lock.foo_bar();
!
// ptr_and_lock destructor is called
// and the end of the fn,
// lock is released
}
Mutex<T>
39. unsafe fn memset(mem: *mut u8, c: u8, len: uint)
{
for i in range(0, len) {
*mem.offset(i as int) = c;
}
}
!
fn main() {
let mut v: Vec<u8> = vec!(1, 2, 3);
unsafe {
memset(v.as_mut_ptr(), 10, v.len());
}
println!("{}", v.to_str());
}
unsafe