C++ Party 2014: Лекция 8. Rust — лучше, чем C++. Кольцов Степан

578

Кольцов Степан рассказал о Rust – современном, практичном, быстром и безопасном языке программирования.

  1. Basic examples
  1. fn main() { println!(«hello world»); } Hello world
  2. fn is_prime(n: uint) -> bool { range(2, n).all(|x| n % x != 0) // lambda
  3. Data types • primitives: bool, int, u32, f32, etc. • builtins: &[], &str • user-defined: struct, enum, trait • functions
  4. struct SocketAddr { host: String, port: uint, } struct
  5. enum CacheStatus { Error(String), Cached(uint), }
  6. fn create_server(conf: Conf) { … }
  7. fn create_server(conf: Conf) { … }
  8. Vec; &[T]; String, &str C++ Rust std::vector<T> std::Vec<T> std::array_view &[T] std::string std::String std::string_view &str
  9. // C++ llvm::ArrayRef<T>; Rust &[T] struct Slice<T> { T* begin; T* end;
  10. // similar to std::vector let v1: Vec<uint> = vec!(10, 20, 30)
  11. fn sum<T>(ns: &[T]) -> T { let sum = T::zero(); for n in ns { sum += n; } n }
  12. Pointers • raw unsafe pointers *Foo • borrowed pointers &Foo • smart pointers
  13. std::string get_url() { return «http://yandex.ru»; }
  14. get_scheme_from_url(string_view url) { unsigned colon = url.find(‘:’); return url.substr(0, colon); }
  15. fn get_url() -> String { «http://yandex.ru».to_string()
  16. struct UrlParts<‘a> { scheme: &’a str, host: &’a str, port: uint, path: &’a str, }
  17. enum MaybeOwned<‘a> { Slice(&’a str), Owned(String)
  18. impl<‘s> MaybeOwned { fn as_slice(&’s self) -> &’s str { match self { Owned(ref s) => s.as_slice(), Slice(s) => s, }
  19. struct Person { name: String
  20. fn longest_str<‘s>(a: &’s str, b: &’s str) -> &’s str { if a.len() > b.len() { a } else { b } }
  21. void foo(vector<int>& xs) { typedef vector<int>::iterator iter; for (iter i = xs.begin(); i
  22. fn foo(xs: &mut Vec<int>) { for p in xs.iter() { if *p == 0 { xs.push(1); } } } Mutability: Rust
  23. let mut a = 1; let b = &mut a; let c = &mut a;
  24. let mut a = 1; a = 2; let b = &a; a = 3
  25. Smart Pointers C++ Rust std::unique_ptr<T> Box<T> std::shared_ptr<T> Rc<T> or Arc<T>
  26. struct Foo { v: int, } ! let ptr = Rc::new(Foo { … }); println!(«{}», ptr.v); User-defined pointers: Rc<T>
  27. struct RcBox<T> { value: T, ref_count: uint, }
  28. Threads • tasks • channels • Arc • AtomicInt • Mutex
  29. 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
  30. 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); }); }
  31. // 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 { … })
  32. Mutex<T> • Mutex<T> = T + mutex • Safely share data between threads
  33. fn do_smth(shared_data: Arc<Mutex<T>>) { // guard + smart pointer let ptr_and_lock = shared_data.lock(); ptr_and_lock.foo_bar()
  34. unsafe fn memset(mem: *mut u8, c: u8, len: uint) { for i in range(0, len) { *mem.offset(i as int) = c; } }
  35. Program performance 0 25 50 75 100 Performance of compiled code C++ Rust Java
  36. Problems • compile-time metaprogramming • IDE • incremental compilation
  37. trait Natural { fn zero() -> Self; fn next(self) -> Self; }
  38. macro_rules! vec( ($($e:expr),*) => ({ let mut _temp = ::std::vec::Vec::new(); $(_temp.push($e);)* _temp }) )
  39. fn print_anything(xs: &[Box<ToStr>]) { for x in xs.iter() { println!(«{}», x.to_str()); } }
  40. class FileInputStream: public InputStream { int fd; }
  41. struct FileInputStream { fd: int } ! impl InputStream for FileInputStream { … }
  42. Fin Stepan Koltsov <nga@yandex-team.ru>