Последние 15 лет между разработчиками на Java и на C++ ведётся спор о том, какой язык программирования хуже — Java или C++. Программы на C++ глючат, падают, и в них утекает память. Программы на Java тормозят и требуют слишком много памяти.
Rust — новый язык программирования, разрабатываемый компанией Mozilla — решает проблемы Java и C++: программы, написанные на Rust, одновременно быстрые и безопасные. Rust является таким же низкоуровневым, close-to-metal языком программирования, как и C++, однако в язык встроены конструкции, позволяющие на этапе компиляции доказывать, что в программе не случится обращения к неинициализированной памяти (механизм borrowed pointers). Большая часть моего рассказа будет посвящена описанию этого механизма.
Rust: код может быть одновременно безопасным и быстрым, Степан Кольцов
1. Rust: modern, practical, safe, fast
programming language
Stepan Koltsov <nga@yandex-team.ru>
Java Party, Kyiv
2. Why Rust
• Java
• Safe*
• … at a price of CPU/mem overhead
• C++
• Very fast
• Very low memory overhead
• Unsafe
• Rust
• As fast as C++*, safer then Java
12. // C++ std::array_view<T>; Rust &[T]
struct Slice<T> {
T* begin;
T* end;
}
!
// C++ std::string_view; Rust: &str
type StrSlice = Slice<char>;
What is slice
13. // 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
14. fn sum<T : Num>(ns: &[T]) -> T {
let sum = T::zero();
for n in ns { sum += n; }
sum
}
traits (type classes)
24. fn common_prefix<'s>(a: &'s str, b: &'s str)
-> &'s str
{ … }
!
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; // error
}
Lifetime intersection
25. void foo(vector<int>& xs) {
typedef vector<int>::iterator iter;
for (iter i = xs.begin(); i != xs.end(); ++i)
{
if (*i == 0) {
// modCount in Java
xs.push_back(1);
}
}
}
Mutability: C++
26.
27. fn foo(xs: &mut Vec<int>) {
for p in xs.iter() {
if *p == 0 {
xs.push(1);
}
}
}
Mutability: Rust
28.
29. 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
30. 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
35. 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
36. 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
37. // 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>
39. fn do_smth(shared_data: Arc<Mutex<T>>) {
// guard + smart pointer
let ptr_and_lock = shared_data.lock();
!
// do smth with guarded object
ptr_and_lock.foo_bar();
!
// ptr_and_lock destructor is called
// and the end of the fn,
// lock is released
}
Mutex<T>
40. 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