Share
Embed
Transcript
88 slides
-
Rust е low-level • Без GC • Почти нулев runtime
• Съвместим със C • Бърз -
Rust е high-level • Пакети • Тестване • Елементи от
функционалното програмиране • Елементи от ООП -
Rust е (доста) безопасен • Няма null • Не позволява
висящи pointer-и • Не позволява double free • Силна статична типова система • Не позволява събирането на flot + int • The Big Deol -
fn main() { let x: i32 = 42; let y:
i32 = x; println!("x = {}", x); println!("y = {}", y); } // =================== x = 42 y = 42 -
fn main() { let x: char = 'ь'; let y:
char = x; println!("x = {}", x); println!("y = {}", y); } // =================== x = ь y = ь -
fn main() { let x: String = String::from("forty-two"); let y:
String = x; println!("x = {}", x); println!("y = {}", y); } // =================== error[E0382]: use of moved value: `x` --> src/main.rs:5:24 | 3 | let y: String = x; | - value moved here 4 | 5 | println!("x = {}", x); | ^ value used here after move | = note: move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait -
fn main() { let x = String::from("forty-two"); if 1 ==
2 { let local = String::new("Inconceivable!"); println!("{}", local); } // local се деалокира println!("{}", x); } // x се деалокира -
fn tell_everybody(news: String) { println!("Ае, хора, {}", news); } fn
main() { let news = String::from("Извънземните нападат!!!"); tell_everybody(news); // println!("{}", news); // => компилационна грешка } -
fn tell_everybody(news: String) -> String { println!("Ае, хора, {}", news);
news } fn main() { let news = String::from("AI превзе света!!!"); let news_i_got_back = tell_everybody(news); println!("{}", news_i_got_back); // println!("{}", news); // => компилаторна грешка } -
fn tell_everybody(news: &String) { println!("Ае, хора, {}", news); } fn
main() { let news = String::from("50% намаление на репички!!!"); tell_everybody(&news); println!("{}", news); } -
Borrow checker • Няма невалидни references • Само един mutable
ref, или • Колкото си искаме immutable refs -
fn main() { let mut fact: String = String::from("Компилатора знае
две"); fact.push_str("и двеста"); println!("{}", &fact); } // =================== Компилатора знае две и двеста -
fn main() { let mut fact: String = String::from("Компилатора знае
две"); let ending: &str = "и двеста"; fact.push_str(ending); println!("{}", &fact); } // =================== Компилатора знае две и двеста -
fn main() { let mut fact: String = String::from("Компилатора знае
две"); let ending: &str = "и двеста"; fact.push_str(ending); println!("{}", fact); let also_true: &str = &fact[0..32]; println!("{}", also_true); } // =================== Компилатора знае две и двеста Компилатора знае -
fn main() { let mut fact: String = String::from("Компилатора знае
две"); let ending: &str = "и двеста"; String::push_str(&mut fact, ending); let also_true: &str = &fact[0..32]; println!("{}", also_true); } // =================== Компилатора знае -
fn main() { let mut fact: String = String::from("Компилатора знае
две"); let ending: &str = "и двеста"; let fact_reference = &mut fact; String::push_str(fact_reference, ending); let also_true: &str = &fact[0..32]; println!("{}", also_true); } // =================== error[E0502]: cannot borrow `fact` as immutable because it is also borrowed as mutable --> src/main.rs:8:28 | 5 | let fact_reference = &mut fact; | ---- mutable borrow occurs here ... 8 | let also_true: &str = &fact[0..32]; | ^^^^ immutable borrow occurs here 9 | println!("{}", also_true); 10 | } | - mutable borrow ends here -
fn main() { let mut fact = String::from("Компилатора знае две");
let also_true = &fact[0..32]; // NOPE fact.push_str(" и двеста"); } -
fn main() { let mut fact = String::from("Компилатора знае две");
{ let also_true = &fact[0..32]; // ... } fact.push_str(" и двеста"); } -
fn main() { let lines = { let mut l
= Vec::with_capacity(4); l.push("Roses are #FF0000,"); l.push("Violets are #0000FF"); l.push("Such a boring example"); l.push("What is wrong with you?"); l }; for line in lines { println!("{}", line); } } -
fn main() { let lines = vec![ "Roses are #FF0000",
"Violets are #0000FF", "Such a boring example", "What is wrong with you?", ]; for line in lines { println!("{}", line); } } -
fn main() { let lines = vec![ "Roses are #FF0000",
"The TARDIS is #0000FF", "A tiny bit better", "With that callback to Doctor Who", ]; for line in lines { println!("{}", line); } } -
fn add(a: i32, b: i32) -> i32 { a +
b } fn main() { let boring_result = add(3, 4); println!("Your boring result: {}", boring_result); } // =================== Your boring result: 7 -
fn add(a: i32, b: i32) -> i32 { a +
b } fn main() { let boring_result = add(3.0, 4.0); println!("Your boring result: {}", boring_result); } // =================== error[E0308]: mismatched types --> src/main.rs:6:29 | 6 | let boring_result = add(3.0, 4.0); | ^^^ expected i32, found floating-point variable | = note: expected type `i32` found type `{float}` -
fn add<T>(a: T, b: T) -> T { a +
b } fn main() { let boring_result = add(3.0, 4.0); println!("Your boring result: {}", boring_result); } // =================== error[E0369]: binary operation `+` cannot be applied to type `T` --> src/main.rs:2:5 | 2 | a + b | ^^^^^ | = note: an implementation of `std::ops::Add` might be missing for `T` -
use std::ops::Add; fn add<T: Add>(a: T, b: T) -> T::Output
{ a + b } fn main() { let boring_result = add(3.0, 4.0); println!("Your boring result: {}", boring_result); } // =================== Your boring result: 7.0 -
trait Add<RHS = Self> { type Output; fn add(self, rhs:
RHS) -> Self::Output; } -
trait Add<RHS = Self> { type Output; fn add(self, rhs:
RHS) -> Self::Output; } impl Add< > for VimUser { type Output = fn add(self, rhs: ) -> Self::Output { } } -
trait Add<RHS = Self> { type Output; fn add(self, rhs:
RHS) -> Self::Output; } impl Add<EmacsUser> for VimUser { type Output = fn add(self, rhs: EmacsUser) -> Self::Output { } } -
trait Add<RHS = Self> { type Output; fn add(self, rhs:
RHS) -> Self::Output; } impl Add<EmacsUser> for VimUser { type Output = ProductiveConversation<MutualRespect>; fn add(self, rhs: EmacsUser) -> Self::Output { // Долу стереотипите! } } -
use std::fmt::Display; fn main() { let displayable: &Display = &5;
println!("{}", displayable); } -
use std::fmt::Display; fn main() { let displayable: Vec<&Display> = vec![&5,
&"baba" as &Display, &3.14]; for d in displayable.iter() { println!("{}", d); } } // The magic of vtables -
Zero-cost abstraction C++ implementations obey the zero-overhead principle: What you
don’t use, you don’t pay for [Stroustrup, 1994]. And further: What you do use, you couldn’t hand code any better. – Stroustrup -
fn main() { let potato = " Любов, любов, варен
картоф, разрежеш го, а той суров. "; println!("--\n{}\n--", potato); } // =================== --- Любов, любов, варен картоф, разрежеш го, а той суров. --- -
fn main() { let potato = " Любов, любов, варен
картоф, разрежеш го, а той суров. "; let lines = potato. trim(). lines(). map(|l| l.trim()); println!("---"); for line in lines { println!("{}", line); } println!("---"); } // =================== --- Любов, любов, варен картоф, разрежеш го, а той суров. --- -
fn main() { let potato = " Любов, любов, варен
картоф, разрежеш го, а той суров. "; let lines = potato. trim(). lines(). map(|l| l.trim()); println!("+-------------------------------+"); for line in lines { println!("| {}\t|", line); } println!("+-------------------------------+"); } // =================== +-------------------------------+ | Любов, любов, варен картоф, | | разрежеш го, а той суров. | +-------------------------------+ -
let lines = potato. trim(). lines(). map(|l| l.trim()); for line
in lines { println!("{}", line); } -
let lines = potato. // => &str trim(). lines(). map(|l|
l.trim()); for line in lines { println!("{}", line); } fn trim(&self) -> &str { // // " Любов, ала-бала, картоф " // ^___________________________^ -> текущия &str // // " Любов, ала-бала, картоф " // ^_____________________^ -> върнатия &str } -
let lines = potato. trim(). lines(). // => Lines (std::str::Lines)
map(|l| l.trim()); for line in lines { println!("{}", line); } // нещо като... impl Iterator for Lines { type Item = &str; fn next() -> Option<Item> { // Some("Любов, любов...") // Some("Картоф, картоф...") // None } } enum Option<T> { Some(T), None, } -
let lines = potato. trim(). lines(). map(|l| l.trim()); for line
in lines { println!("{}", line); } -
let lines = potato. trim(). lines(). map(|l| l.trim()); // =>
std::iter::Map<std::str::Lines<'_>, [closure@src/main.rs:10:13: 10:25]> for line in lines { println!("{}", line); } -
let lines = potato. trim(). lines(). map(|l| l.trim()); for line
in lines { println!("{}", line); } |l| l.trim() // се превежда до нещо като... struct PotatoClosure { // ... прихванати променливи } impl Fn(&str) -> &str for PotatoClosure { fn call(&self, l: &str) -> &str { l.trim() } } -
let lines = potato. trim(). lines(). map(|l| l.trim()); for line
in lines { println!("{}", line); } -
fn main() { let potato = " Любов, любов, варен
картоф, разрежеш го, а той суров. "; let lines = potato. trim(). lines(). map(|l| l.trim()); for line in lines { println!("{}", line); } } -
fn main() { let potato = String::from(" Любов, любов, варен
картоф, разрежеш го, а той суров. "); let lines = potato. as_str(). trim(). lines(). map(|l| l.trim()); for line in lines { println!("{}", line); } } -
use std::fs::File; use std::io::Read; fn main() { let mut file
= File::open("boring.txt"); let mut contents = String::new(); file.read_to_string(&mut contents); println!("{}", contents); } //==================== error[E0599]: no method named `read_to_string` found for type `std::result::Result<std::fs::File, std::io::Error>` in the current scope --> src/main.rs:7:7 | 7 | f.read_to_string(&mut contents); | ^^^^^^^^^^^^^^ error: aborting due to previous error -
enum Result<T, E> { Ok(T), Err(E), } // Error handling
in C be like: open("excellent_file.txt", "r") // => 15 open("broken_file.txt") // -1 errno // -17 // In Rust: File::open("excellent_file.txt") // => Ok(File) File::open("broken_file.txt") // => Err("you're err is -17") -
use std::fs::File; use std::io::Read; fn main() { let mut file
= match File::open("boring.txt") { Ok(f) => f, Err(e) => panic!("OH, NO! {}", e), }; let mut contents = String::new(); file.read_to_string(&mut contents); println!("{}", contents); } //==================== Компилационна грешка (ха-ха, това е буквалното съдържание на файла) -
use std::fs::File; use std::io::Read; fn main() { do_magic_stuff(); } fn
do_magic_stuff() { let mut boring = match File::open("boring.txt") { Ok(f) => f, Err(e) => panic!("OH, NO! {}", e), }; let mut fun = match File::open("fun.txt") { Ok(f) => f, Err(e) => panic!("OH, NO! {}", e), }; let mut contents = String::new(); boring.read_to_string(&mut contents); fun.read_to_string(&mut contents); println!("{}", contents); } -
use std::fs::File; use std::io::{self, Read}; fn main() { match do_magic_stuff()
{ Ok(contents) => println!("{}", contents), Err(e) => panic!("OH, NO! {}", e), } } fn do_magic_stuff() -> Result<String, io::Error> { let mut boring = match File::open("boring.txt") { Ok(f) => f, Err(e) => return Err(e), }; let mut fun = match File::open("fun.txt") { Ok(f) => f, Err(e) => return Err(e), }; let mut contents = String::new(); boring.read_to_string(&mut contents); fun.read_to_string(&mut contents); return Ok(contents); } -
macro_rules! try { ($expr:expr) => { match $expr { Ok(result)
=> result, Err(e) => return Err(e), } } } -
use std::fs::File; use std::io::{self, Read}; fn main() { match do_magic_stuff()
{ Ok(contents) => println!("{}", contents), Err(e) => panic!("OH, NO! {}", e), } } fn do_magic_stuff() -> Result<String, io::Error> { let mut boring = match File::open("boring.txt") { Ok(f) => f, Err(e) => return Err(e), }; let mut fun = match File::open("fun.txt") { Ok(f) => f, Err(e) => return Err(e), }; let mut contents = String::new(); boring.read_to_string(&mut contents); fun.read_to_string(&mut contents); return Ok(contents); } -
use std::fs::File; use std::io::{self, Read}; fn main() { match do_magic_stuff()
{ Ok(contents) => println!("{}", contents), Err(e) => panic!("OH, NO! {}", e), } } fn do_magic_stuff() -> Result<String, io::Error> { let mut boring = try!(File::open("boring.txt")); let mut fun = try!(File::open("fun.txt")); let mut contents = String::new(); boring.read_to_string(&mut contents); fun.read_to_string(&mut contents); return Ok(contents); } -
fn main() { let contents = try!(do_magic_stuff()); println!("{}", contents), }
//==================== error[E0308]: mismatched types --> src/main.rs:8:30 | 8 | Err(e) => return Err(e), | ^^^^^^ expected (), found enum `std::result::Result` ... 14 | try!(do_magic_stuff()); | ----------------------- in this macro invocation | = note: expected type `()` found type `std::result::Result<_, std::io::Error>` -
let mut fun = try!(File::open("fun.txt")); let mut fun = try!
{ File::open("fun.txt"). or_else(|_| File::open("passable.txt")). or_else(|_| File::open("okay_i_guess.txt")) }; let optional_fun = File::open("fun.txt"). or_else(|_| File::open("passable.txt")). or_else(|_| File::open("okay_i_guess.txt")); if let Ok(mut fun) = optional_fun { // Super-special Fun Time! } -
fn main() { let args: Vec<String> = std::env::args().collect(); if args.len()
> 0 { let filename = args.get(0); // Oh, no! Some(String)! -
fn main() { let args: Vec<String> = std::env::args().collect(); if args.len()
> 0 { let filename = args.get(0).unwrap(); run_interpreter(filename) } else { run_console(); } } -
fn main() { let args: Vec<String> = std::env::args().collect(); if args.len()
> 1 { let filename = args.get(1).unwrap(); run_interpreter(filename) } else { run_console(); } } -
fn main() { let args: Vec<String> = std::env::args().collect(); if args.len()
> 2 { let filename = args.get(2).unwrap(); run_interpreter(filename) } else { run_console(); } } -
fn main() { let args: Vec<String> = std::env::args().collect(); if args.len()
>= 3 { let filename = args.get(3).unwrap(); run_interpreter(filename) } else { run_console(); } } // =================== thread 'main' panicked at 'called `Option::unwrap()` on a `None` value', /checkout/src/libcore/option.rs:335:20 note: Run with `RUST_BACKTRACE=1` for a backtrace. -
fn main() { let args: Vec<String> = std::env::args().collect(); match args.get(0)
{ Some(filename) => run_interpreter(filename), None => run_console(), } } -
Learning curve • Ownership • Borrow checker • Mutability •
Pattern-matching • Lifetimes -
Заслужава си • Redox (+ coreutils + terminal + shell)
• Игри (ggez, Piston, SHAR) • 100+ “Friends of Rust” -
fn main() { let x: String = String::from("forty-two"); let y:
String = x; println!("x = {}", x); println!("y = {}", y); } // =================== error[E0382]: use of moved value: `x` --> src/main.rs:5:24 | 3 | let y: String = x; | - value moved here 4 | 5 | println!("x = {}", x); | ^ value used here after move | = note: move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait