98
Rust 2019 compscicenter.ru [email protected]

Лекция 1: Введение · Jav a ( 3 0 m s) v s R u st ( 1 7 m s) Функция не аллоцирует объекты, единственная разница — в

  • Upload
    others

  • View
    3

  • Download
    0

Embed Size (px)

Citation preview

Page 1: Лекция 1: Введение · Jav a ( 3 0 m s) v s R u st ( 1 7 m s) Функция не аллоцирует объекты, единственная разница — в

Rust 2019compscicenter.ru

[email protected]

Page 2: Лекция 1: Введение · Jav a ( 3 0 m s) v s R u st ( 1 7 m s) Функция не аллоцирует объекты, единственная разница — в

Лекция 1: Введение

Page 3: Лекция 1: Введение · Jav a ( 3 0 m s) v s R u st ( 1 7 m s) Функция не аллоцирует объекты, единственная разница — в

Про курс

Научиться программировать на Rust?

Устроиться на работу?

1/96

Page 4: Лекция 1: Введение · Jav a ( 3 0 m s) v s R u st ( 1 7 m s) Функция не аллоцирует объекты, единственная разница — в

Про курс

Научиться думать о программах по-другому.

Углубить понимание современного C++.

2/96

Page 5: Лекция 1: Введение · Jav a ( 3 0 m s) v s R u st ( 1 7 m s) Функция не аллоцирует объекты, единственная разница — в

Про меняhttps://github.com/matklad

IntelliJ Rust

Cargo (система сборки Rust)

rls 2.0 😨

3/96

Page 6: Лекция 1: Введение · Jav a ( 3 0 m s) v s R u st ( 1 7 m s) Функция не аллоцирует объекты, единственная разница — в

Про Rust1.0 в 2015 году

нет сборщика мусора

минимальный runtime

конкурент C++

memory safety (!)

4/96

Page 7: Лекция 1: Введение · Jav a ( 3 0 m s) v s R u st ( 1 7 m s) Функция не аллоцирует объекты, единственная разница — в

Что такое Runtime?runtime

код "вокруг" вашей программы.

Типичные компоненты:сборщик мусора

интерпретатор

JIT компилятор

представление значений в памяти

5/96

Page 8: Лекция 1: Введение · Jav a ( 3 0 m s) v s R u st ( 1 7 m s) Функция не аллоцирует объекты, единственная разница — в

Цена RuntimeRuntime это замечательно!Чем больше делает runtime, тем меньше надо делать вам. Но:

скорость

размер

переиспользование

6/96

Page 9: Лекция 1: Введение · Jav a ( 3 0 m s) v s R u st ( 1 7 m s) Функция не аллоцирует объекты, единственная разница — в

Zero Cost AbstractionsКлючевой момент философии C++ и Rust:

высокоуровневые конструкции бесплатны во времяисполнения программы

Хорошая философия, когда ресурсы ограничены.

7/96

Page 10: Лекция 1: Введение · Jav a ( 3 0 m s) v s R u st ( 1 7 m s) Функция не аллоцирует объекты, единственная разница — в

Пример (Java)

private static double average(int[] data) { int sum = 0; for (int i = 0; i < data.length; i++) { sum += data[i]; } return sum * 1.0d / data.length; }

$ java MainJ 30 ms

8/96

Page 11: Лекция 1: Введение · Jav a ( 3 0 m s) v s R u st ( 1 7 m s) Функция не аллоцирует объекты, единственная разница — в

Пример (Rust)

fn average(xs: &[i32]) -> f64 { let mut sum: i32 = 0; for i in 0..xs.len() { sum += xs[i]; } sum as f64 / xs.len() as f64 }

$ ./target/release/avg ???

9/96

Page 12: Лекция 1: Введение · Jav a ( 3 0 m s) v s R u st ( 1 7 m s) Функция не аллоцирует объекты, единственная разница — в

Пример (Rust)

fn average(xs: &[i32]) -> f64 { let mut sum: i32 = 0; for i in 0..xs.len() { sum += xs[i]; } sum as f64 / xs.len() as f64 }

$ ./target/release/avg 17 ms

10/96

Page 13: Лекция 1: Введение · Jav a ( 3 0 m s) v s R u st ( 1 7 m s) Функция не аллоцирует объекты, единственная разница — в

Пример (Scala)

def average(x: Array[Int]): Double = { x.reduce(_ + _) * 1.0 / x.size }

$ scala MainS 518 ms

11/96

Page 14: Лекция 1: Введение · Jav a ( 3 0 m s) v s R u st ( 1 7 m s) Функция не аллоцирует объекты, единственная разница — в

Пример (и снова Rust)

fn average(xs: &[i32]) -> f64 { xs.iter().fold(0, |x, y| x + y) as f64 / xs.len() as f64 }

$ ./target/release/avg 18 ms

12/96

Page 15: Лекция 1: Введение · Jav a ( 3 0 m s) v s R u st ( 1 7 m s) Функция не аллоцирует объекты, единственная разница — в

АнализJava (30 ms) vs Rust (17 ms)

Функция не аллоцирует объекты, единственная разница — вгенерации кода.

Java (30 ms) vs Scala (518 ms)

Функции работают с объектами ⇒ боксинг.

Rust (17 ms) vs Rust (18 ms)

Функция — бесплатная абстракция.

13/96

Page 16: Лекция 1: Введение · Jav a ( 3 0 m s) v s R u st ( 1 7 m s) Функция не аллоцирует объекты, единственная разница — в

Зачем нужен Runtime?Автоматическое управление памятью — огромная экономиявремени программиста

Закон Амдала — время работы программы не важно, если 90%это IO

Ручное управление памятью — путь к катастрофическимошибкам

Последний пункт — разница между C++ и Rust.

14/96

Page 17: Лекция 1: Введение · Jav a ( 3 0 m s) v s R u st ( 1 7 m s) Функция не аллоцирует объекты, единственная разница — в

Где используется Rust?

браузеры: Servo и Firefox

операционные системы: Fuschia

криптовалюты: Parity, Exonum

базы данных: TiKV

15/96

Page 18: Лекция 1: Введение · Jav a ( 3 0 m s) v s R u st ( 1 7 m s) Функция не аллоцирует объекты, единственная разница — в

Hello, world

fn main() { println!("Hello, World!"); }

$ rustc main.rs # без оптимизаций $ ./main Hello, World!

16/96

Page 19: Лекция 1: Введение · Jav a ( 3 0 m s) v s R u st ( 1 7 m s) Функция не аллоцирует объекты, единственная разница — в

Hello, world

#![no_main] #[link_section=".text"] #[no_mangle] pub static main: [u32; 9] = [ 3237986353, 3355442993, 120950088, 822083584, 252621522, 1699267333, 745499756, 1919899424, 169960556, ];

17/96

Page 20: Лекция 1: Введение · Jav a ( 3 0 m s) v s R u st ( 1 7 m s) Функция не аллоцирует объекты, единственная разница — в

Hello, Cargo

https://rustup.rs/

$ cargo new hello-world Created binary (application) `hello-world` package $ cargo run --release Compiling hello-world v0.1.0 (/home/matklad/hello-world) Finished release [optimized] target(s) in 0.50s Running `target/release/hello-world` Hello, world!

18/96

Page 21: Лекция 1: Введение · Jav a ( 3 0 m s) v s R u st ( 1 7 m s) Функция не аллоцирует объекты, единственная разница — в

Основные Типы

19/96

Page 22: Лекция 1: Введение · Jav a ( 3 0 m s) v s R u st ( 1 7 m s) Функция не аллоцирует объекты, единственная разница — в

Целые числа

кол-во бит 8 16 32 64 128 32/64

Знаковые i8 i16 i32 i64 i128 isize

Беззнаковые u8 u16 u32 u64 u128 usize

usize — размер указателя

20/96

Page 23: Лекция 1: Введение · Jav a ( 3 0 m s) v s R u st ( 1 7 m s) Функция не аллоцирует объекты, единственная разница — в

Целые числаЛитералы — целое число + суффикс

Тип литерала без суффикса выводится из контекста

По умолчанию — i32

let y = 92_000_000i64; let hex_octal_bin = 0xffff_ffff + 0o777 + 0b1; let byte: u8 = b'a'; assert_eq!(byte, 65);

let idx: usize = 92;

let int = 92; println!("{}", int);

21/96

Page 24: Лекция 1: Введение · Jav a ( 3 0 m s) v s R u st ( 1 7 m s) Функция не аллоцирует объекты, единственная разница — в

Арифметикаарифметические операции: + , - , * , /

/ , % округляют к 0

битовые/логические операции: << , >> , | , & , ^

инверсия битов: !

нет оператора возведения в степень

нет ++

методы: (-92i32).abs() , 0b001100u8.count_ones()

22/96

Page 25: Лекция 1: Введение · Jav a ( 3 0 m s) v s R u st ( 1 7 m s) Функция не аллоцирует объекты, единственная разница — в

АрифметикаНет неявного приведения типов

as — оператор явного приведения типов

let x: u16 = 1; let y: u32 = x; // error: mismatched types let y: u32 = x.into(); // Расширение без потери точности let z: u16 = y as u16; // Берём младшие биты let to_usize = 92u64 as usize; let from_usize = 92usize as u64;

23/96

Page 26: Лекция 1: Введение · Jav a ( 3 0 m s) v s R u st ( 1 7 m s) Функция не аллоцирует объекты, единственная разница — в

АрифметикаПереполнение — ошибка программиста

fn main() { let x = i32::max_value(); let y = x + 1; println!("{}", y); }

$ cargo run thread 'main' panicked at 'attempt to add with overflow', main.rs:3:13 $ cargo run --release -2147483648

24/96

Page 27: Лекция 1: Введение · Jav a ( 3 0 m s) v s R u st ( 1 7 m s) Функция не аллоцирует объекты, единственная разница — в

АрифметикаЯвная арифметика с переполнением

let x = i32::max_value(); let y = x.wrapping_add(1); assert_eq!(y, i32::min_value()); let y = x.saturating_add(1); assert_eq!(y, i32::max_value()); let (y, overflowed) = x.overflowing_add(1); assert!(overflowed); assert_eq!(y, i32::min_value()) match x.checked_add(1) { Some(y) => unreachable!(), None => println!("overflowed"), }

25/96

Page 28: Лекция 1: Введение · Jav a ( 3 0 m s) v s R u st ( 1 7 m s) Функция не аллоцирует объекты, единственная разница — в

Переполнение в C++

Переполнение знакового типа в C или C++ — unde�ned behavior

Что такое неопределённое поведение?

1. Результат операции зависит от архитектуры?

2. Результатом может быть любое число?

3. Инструкция оптимизатору: "такого не может быть".

26/96

Page 29: Лекция 1: Введение · Jav a ( 3 0 m s) v s R u st ( 1 7 m s) Функция не аллоцирует объекты, единственная разница — в

main.cpp

#include <climits> #include <iostream> bool will_overflow(int x) { return x > x + 1; } int main() { std::cout << will_overflow(INT_MAX) << std::endl; }

$ clang main.cpp -O0 && ./a.out 1 $ clang main.cpp -O2 && ./a.out 0

27/96

Page 30: Лекция 1: Введение · Jav a ( 3 0 m s) v s R u st ( 1 7 m s) Функция не аллоцирует объекты, единственная разница — в

With unde�ned behavior anything is possible

28/96

Page 31: Лекция 1: Введение · Jav a ( 3 0 m s) v s R u st ( 1 7 m s) Функция не аллоцирует объекты, единственная разница — в

Польза UB

Оптимизация: замена индексации на указатели

Размер указателя — 64 бита, размер int — 32 бита.Трансформация верна только если переполнение int неопределено.

for (int i = 0; i < m; ++i) { foo(xs[i]); }

for (T* it = &xs[0]; it < &xs[m]; ++it) { foo(*it); }

29/96

Page 32: Лекция 1: Введение · Jav a ( 3 0 m s) v s R u st ( 1 7 m s) Функция не аллоцирует объекты, единственная разница — в

UB в RustКлючевой момент философии Rust, и главное отличие от C++:

Проверка типов гарантирует отсутствие UB

Существуют unsafe операции: компилятор не может проверитьих корректность, но требует явного блока unsafe { } .

*

30/96

Page 33: Лекция 1: Введение · Jav a ( 3 0 m s) v s R u st ( 1 7 m s) Функция не аллоцирует объекты, единственная разница — в

Арифметика в стиле C++

такой функции пока нет

программист обязан гарантировать отсутствие переполнения

компилятор верит и использует при оптимизации

коллеги программиста видят ( ) unsafe

let x = 92; let y = unsafe { x.unchecked_add(1) };

Ctrl+f

31/96

Page 34: Лекция 1: Введение · Jav a ( 3 0 m s) v s R u st ( 1 7 m s) Функция не аллоцирует объекты, единственная разница — в

Числа с плавающей точкой (IEEE-754)

f32 f64

let y = 0.0f32; // литерал f32 let x = 0.0; // тип выводится, f64 по умолчанию // точка обязательна let z: f32 = 0; // error: expected f32, found integer variable let z: f32 = 0.0; let not_a_number: f32 = std::f32::NAN; let inf: f32 = std::f32::INFINITY; // есть куча методов 8.5f32.ceil().sin().round().sqrt()

32/96

Page 35: Лекция 1: Введение · Jav a ( 3 0 m s) v s R u st ( 1 7 m s) Функция не аллоцирует объекты, единственная разница — в

Логический тип

&& и || “ленивые”

нет неявного приведения к bool

let to_be: bool = true; let not_to_be = !to_be; let the_question = to_be || not_to_be;

let i = 1; let b: bool = i == 0; let i = b as i32;

33/96

Page 36: Лекция 1: Введение · Jav a ( 3 0 m s) v s R u st ( 1 7 m s) Функция не аллоцирует объекты, единственная разница — в

Кортежи

() (i32,) (i32, i64)

let pair: (f32, i32) = (0.0, 92); let (x, y) = pair; let x = pair.0; let y = pair.1; let void_result = println!("hello"); assert_eq!(void_result, ()); let trailing_comma = ( "Archibald", "Buttle", );

34/96

Page 37: Лекция 1: Введение · Jav a ( 3 0 m s) v s R u st ( 1 7 m s) Функция не аллоцирует объекты, единственная разница — в

КортежиВ памяти (i32, i32) это пара интов (8 байт):

7 07 00 00 00

(7, 263) 07 00 00 00 07 01 00 00

Объединение типов в кортеж — zero cost abstraction.[1]

35/96

Page 38: Лекция 1: Введение · Jav a ( 3 0 m s) v s R u st ( 1 7 m s) Функция не аллоцирует объекты, единственная разница — в

Кортежиmain.rs

main.py

fn main() { let t = (92,); println!("{:?}", &t as *const (i32,)); // 0x7ffc6b2f6aa4 println!("{:?}", &t.0 as *const i32); // 0x7ffc6b2f6aa4 }

t = (92,) print(id(t)) # 139736506707248 print(id(t[0])) # 139736504680928

36/96

Page 39: Лекция 1: Введение · Jav a ( 3 0 m s) v s R u st ( 1 7 m s) Функция не аллоцирует объекты, единственная разница — в

Массивы

[i32; 0] [i32; 1] [i32; 10]

размер массива — константа, часть типа

[i8; 3] это примерно то же самое, что и (u8, u8, u8) .

let xs: [u8; 3] = [1, 2, 3]; assert_eq!(xs[0], 1); // index -- usize assert_eq!(xs.len(), 3); // len() -- usize let mut buf = [0u8; 1024];

37/96

Page 40: Лекция 1: Введение · Jav a ( 3 0 m s) v s R u st ( 1 7 m s) Функция не аллоцирует объекты, единственная разница — в

Ссылки

&T &mut T

подробности — в следующей лекции

представление ссылки — указатель

не может быть NULL

гарантирует, что объект жив

let mut x: i32 = 92; let r: &mut i32 = &mut 92; // явное взятие ссылки *r += 1; // явное разыменовывание ссылки

38/96

Page 41: Лекция 1: Введение · Jav a ( 3 0 m s) v s R u st ( 1 7 m s) Функция не аллоцирует объекты, единственная разница — в

Указатели

*const T *mut T

могут быть NULL

не гарантируют, что объект жив

разыменовывание указателя — unsafe операция

встречаются редко (� и продвинутые структуры данных)

39/96

Page 42: Лекция 1: Введение · Jav a ( 3 0 m s) v s R u st ( 1 7 m s) Функция не аллоцирует объекты, единственная разница — в

Box

Box<T>

указатель на данные в куче

не может быть NULL

Box::new выделяет память

память освобождается на выходе из области видимости

Для любителей C++: std::unique_ptr

let x: Box<i32> = Box::new(92);

40/96

Page 43: Лекция 1: Введение · Jav a ( 3 0 m s) v s R u st ( 1 7 m s) Функция не аллоцирует объекты, единственная разница — в

Стек

fn foo() { let a = 1; let b = bar(); } fn bar() -> i32 { let c = 2; 92 }

41/96

Page 44: Лекция 1: Введение · Jav a ( 3 0 m s) v s R u st ( 1 7 m s) Функция не аллоцирует объекты, единственная разница — в

Куча

fn foo() { let a: Box<i32>; a = Box::new(1); bar(&*a) } fn bar(b: &i32) { }

42/96

Page 45: Лекция 1: Введение · Jav a ( 3 0 m s) v s R u st ( 1 7 m s) Функция не аллоцирует объекты, единственная разница — в

Стек

быстро: сложить два числа

автоматическое освобождение

время жизни привязано к функции

размер известен во время компиляции

Куча

медленнее: insert / remove в дереве, синхронизация

явные malloc и free

произвольное время жизни

любой размер

43/96

Page 46: Лекция 1: Введение · Jav a ( 3 0 m s) v s R u st ( 1 7 m s) Функция не аллоцирует объекты, единственная разница — в

Стек

локален для потока

адресное пространство выделяется при старте потока (8mb)

маппинг в физическую память ленивый

если очень хочется, можно поменять после старта потока

guard page

Куча

глобальна для процесса

mmap , brk для выделения адресного пространства

аллокатор для распределения памяти

44/96

Page 47: Лекция 1: Введение · Jav a ( 3 0 m s) v s R u st ( 1 7 m s) Функция не аллоцирует объекты, единственная разница — в

Как узнать, когда можно делать free ?Сборка мусора

Динамически считаем живые указатели на объекты,освобождаем недостижимую память. Uni�ed theory of grabage collection

Rust

Статически освобождаем память в фиксированном месте,запрещаем убегающие указатели. RAII? Статическая сборка мусора? Счётчик ссылок в F ?2

45/96

Page 48: Лекция 1: Введение · Jav a ( 3 0 m s) v s R u st ( 1 7 m s) Функция не аллоцирует объекты, единственная разница — в

Память освобождается при выходе из области видимости ( {} )

fn foo() { let x = Box::new(92); // вызов alloc let r: &i32 = &x; use_x(r); // неявный вызов dealloc } fn use_x(x: &i32) { }

46/96

Page 49: Лекция 1: Введение · Jav a ( 3 0 m s) v s R u st ( 1 7 m s) Функция не аллоцирует объекты, единственная разница — в

fn foo() { let r: &i32; { let x = Box::new(92); r = &*x; } use_x(r); } fn use_x(x: &i32) { }

47/96

Page 50: Лекция 1: Введение · Jav a ( 3 0 m s) v s R u st ( 1 7 m s) Функция не аллоцирует объекты, единственная разница — в

fn foo() { let r: &i32; { let x = Box::new(92); r = &*x; // borrowed value does not live long enough } use_x(r); } fn use_x(x: &i32) { }

48/96

Page 51: Лекция 1: Введение · Jav a ( 3 0 m s) v s R u st ( 1 7 m s) Функция не аллоцирует объекты, единственная разница — в

Проблема

Если память освобождается на выходе из блока, то мы освободимеё дважды?

fn foo() { let x = Box::new(92); let y = x; }

49/96

Page 52: Лекция 1: Введение · Jav a ( 3 0 m s) v s R u st ( 1 7 m s) Функция не аллоцирует объекты, единственная разница — в

Присваивание (move)Компилятор поддерживает множество инициализированныхпеременных, присваивание "тратит" правую часть

при-сво-ить

завладеть, самовольно взять в свою собственность, выдать засвоё.

// init uninit let y; // y let x; // x, y let x = Box::new(92); // x y let t = x; // t x, y let y = t; // y x, t // y освобождает память

50/96

Page 53: Лекция 1: Введение · Jav a ( 3 0 m s) v s R u st ( 1 7 m s) Функция не аллоцирует объекты, единственная разница — в

Примеры

use after move

let spam = Box::new(92); let eggs = spam; println!("{}", spam); // use of moved value spam

51/96

Page 54: Лекция 1: Введение · Jav a ( 3 0 m s) v s R u st ( 1 7 m s) Функция не аллоцирует объекты, единственная разница — в

Примеры

вызов функции

fn foo() { let x = Box::new(92); // alloc bar(x); // x тут не определён } fn bar(x: Box<i32>) { // dealloc }

52/96

Page 55: Лекция 1: Введение · Jav a ( 3 0 m s) v s R u st ( 1 7 m s) Функция не аллоцирует объекты, единственная разница — в

dropВызов функции это move: напишем удалятор переменных

Функция drop доступна из коробки

fn drop<T>(_value: T) { } fn foo() { let x = Box::new(1); let y = Box::new(2); drop(y); drop(x); }

53/96

Page 56: Лекция 1: Введение · Jav a ( 3 0 m s) v s R u st ( 1 7 m s) Функция не аллоцирует объекты, единственная разница — в

Аффинные типы

Обычная типизация

condition , then_branch , else_branch могут использовать x

Линейная типизация

нужно использовать x ровно один раз.

Аффинная типизация

можно использовать x , но не более одного раза.

let x: T = foo() in if condition then then_branch else else_branch

54/96

Page 57: Лекция 1: Введение · Jav a ( 3 0 m s) v s R u st ( 1 7 m s) Функция не аллоцирует объекты, единственная разница — в

Аффинные типыlet x = 92 in

if x > 0 then x else -x только обычная типизация

if x > 0 then y else z все три варианта

if y > 0 then x else -x все три варианта

if y > 0 then x else z афинная, но не линейная

55/96

Page 58: Лекция 1: Введение · Jav a ( 3 0 m s) v s R u st ( 1 7 m s) Функция не аллоцирует объекты, единственная разница — в

Обычные типы

Г ⊢ t : T →T Г ⊢ t : T ━━━━━━━━━━━━━━━━━━━━━━━━━━━━

Г ⊢ t t : T

1 11 12 2 11

1 2 12

56/96

Page 59: Лекция 1: Введение · Jav a ( 3 0 m s) v s R u st ( 1 7 m s) Функция не аллоцирует объекты, единственная разница — в

Афинные типы

строим разбиение контекста для проверкиподвыражений

Г ⊢ t : T →T Г ⊢ t : T Г = Г ⊔ Г ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

Г ⊢ t t : T

1 1 11 12 2 2 11 1 2

1 2 12

57/96

Page 60: Лекция 1: Введение · Jav a ( 3 0 m s) v s R u st ( 1 7 m s) Функция не аллоцирует объекты, единственная разница — в

ПроблемаА что если присваиваем в зависимости от условия?

let x = Box::new(92); let y; let z; if condition { y = x; } else { z = x; } // Кто освобождает память, x или y?

58/96

Page 61: Лекция 1: Введение · Jav a ( 3 0 m s) v s R u st ( 1 7 m s) Функция не аллоцирует объекты, единственная разница — в

Drop �agsА что если присваиваем в зависимости от условия?

Невидимый флаг на стеке: инициализирована ли переменная?Очень маленький счётчик ссылок :o)

let x = Box::new(92); let y; let z; if condition { y = x; } else { z = x; } // Кто освобождает память, x или y?

59/96

Page 62: Лекция 1: Введение · Jav a ( 3 0 m s) v s R u st ( 1 7 m s) Функция не аллоцирует объекты, единственная разница — в

Vec

Vec<T>

расширяющийся массив

Box для n элементов

pub struct Vec<T> { /// Указатель на данные в куче. ptr: *const T, /// Количество элементов в векторе. /// Инвариант: len <= capacity. len: usize, /// Количество слотов в векторе (capacity). /// Увеличивается в 2 раза при заполнении. cap: usize, }

60/96

Page 63: Лекция 1: Введение · Jav a ( 3 0 m s) v s R u st ( 1 7 m s) Функция не аллоцирует объекты, единственная разница — в

Vec

use std::mem::size_of; assert_eq!( size_of::<Vec<i32>>(), size_of::<usize>() * 3, ); let mut xs = vec![1, 2, 3]; xs.push(4); assert_eq!(xs.len(), 4); assert_eq!(xs[2], 3);

61/96

Page 64: Лекция 1: Введение · Jav a ( 3 0 m s) v s R u st ( 1 7 m s) Функция не аллоцирует объекты, единственная разница — в

Vec

let ys; let xs = vec![1, 2, 3]; ys = xs;

62/96

Page 65: Лекция 1: Введение · Jav a ( 3 0 m s) v s R u st ( 1 7 m s) Функция не аллоцирует объекты, единственная разница — в

Vec

let ys; let xs = vec![1, 2, 3]; ys = xs;

63/96

Page 66: Лекция 1: Введение · Jav a ( 3 0 m s) v s R u st ( 1 7 m s) Функция не аллоцирует объекты, единственная разница — в

Vec

let ys; let xs = vec![1, 2, 3]; ys = xs.clone();

64/96

Page 67: Лекция 1: Введение · Jav a ( 3 0 m s) v s R u st ( 1 7 m s) Функция не аллоцирует объекты, единственная разница — в

Виды присваивания

Python: увеличим счётчик ссылок.

Java: копируем указатель, сборщик мусора на него посмотритпотом (+ опциональный барьер).

C++: делаем глубокую копию объекта.

Rust: в compile-time пометим ys как неинициализированную,в runtime скопируем байты на стеке.

xs = ys

65/96

Page 68: Лекция 1: Введение · Jav a ( 3 0 m s) v s R u st ( 1 7 m s) Функция не аллоцирует объекты, единственная разница — в

Rust

move это memcpy size_of::<T> байт

есть всегда, не может завершиться с ошибкой

поведение по умолчанию

копирование — явный вызов .clone

C++

можно перегрузить move конструктор

есть не всегда, может кинуть исключение

по умолчанию — копирование (за исключением rvalue-ссылок)

совместимость с C++98

66/96

Page 69: Лекция 1: Введение · Jav a ( 3 0 m s) v s R u st ( 1 7 m s) Функция не аллоцирует объекты, единственная разница — в

Представление объектов в памятиCPU существенно быстрее RAM

кэш существенно меньше и быстрее RAM

разыменовывание указателя — дорогая операция

компилятор может сгенерировать эффективный код

компилятор не может поменять структуру данных

67/96

Page 70: Лекция 1: Введение · Jav a ( 3 0 m s) v s R u st ( 1 7 m s) Функция не аллоцирует объекты, единственная разница — в

Rust/C++

stack:

heap:

ptr

x1

len

y1

cap

x2

p

y2

struct Point { x: f64, y: f64} let xs: Vec<Point> = ...; let p: &Point = xs[0];

68/96

Page 71: Лекция 1: Введение · Jav a ( 3 0 m s) v s R u st ( 1 7 m s) Функция не аллоцирует объекты, единственная разница — в

Java

stack:

heap:

x1 y1

ptr

xs

p1

len

p

p1

x2

cap

y2

class Point { double x; double y; } ArrayList xs = ...; Point p = xs.get(0);

69/96

Page 72: Лекция 1: Введение · Jav a ( 3 0 m s) v s R u st ( 1 7 m s) Функция не аллоцирует объекты, единственная разница — в

Краткий курс ссылок

fn print_vec(xs: Vec<i32>) { for x in xs { println!("{}", x); } } fn main() { let xs = vec![1, 2, 3]; print_vec(xs); // ok print_vec(xs); // value used after move }

70/96

Page 73: Лекция 1: Введение · Jav a ( 3 0 m s) v s R u st ( 1 7 m s) Функция не аллоцирует объекты, единственная разница — в

Краткий курс ссылок (borrowing)

& позволяет использовать значение, не меняя структурывладения

fn print_vec(xs: &Vec<i32>) { for x in xs { println!("{}", x); } } fn main() { let xs = vec![1, 2, 3]; print_vec(&xs); // ok print_vec(&xs); // ok }

71/96

Page 74: Лекция 1: Введение · Jav a ( 3 0 m s) v s R u st ( 1 7 m s) Функция не аллоцирует объекты, единственная разница — в

Краткий курс ссылок (borrowing)

&mut позволяет менять значение

fn print_vec_sorted(xs: &mut Vec) { xs.sort(); for x in xs { println!("{}", x); } } fn main() { let xs = vec![1, 2, 3]; print_vec_sorted(&mut xs); // ok print_vec_sorted(&mut xs); // ok }

72/96

Page 75: Лекция 1: Введение · Jav a ( 3 0 m s) v s R u st ( 1 7 m s) Функция не аллоцирует объекты, единственная разница — в

Выражения

73/96

Page 76: Лекция 1: Введение · Jav a ( 3 0 m s) v s R u st ( 1 7 m s) Функция не аллоцирует объекты, единственная разница — в

Выражения

C с ароматом ML

почти все конструкции — выражения

74/96

Page 77: Лекция 1: Введение · Jav a ( 3 0 m s) v s R u st ( 1 7 m s) Функция не аллоцирует объекты, единственная разница — в

Блоки{} — выражение

Блок состоит из инструкций (statement), завершённых ;Значение блока — значение хвостового выражения.

Точки с запятой имеют значение!

1 + { let x = 2; x * 2 }

let i: i32 = { 1 }; let i: () = { 1; };

75/96

Page 78: Лекция 1: Введение · Jav a ( 3 0 m s) v s R u st ( 1 7 m s) Функция не аллоцирует объекты, единственная разница — в

Инициализация блоком

// Лишние переменные не видны снаружи let omelet = { let eggs = get_eggs(&mut refrigerator, 3); let bacon = open_bacon(&mut refrigerator); fry(eggs, bacon) };

76/96

Page 79: Лекция 1: Введение · Jav a ( 3 0 m s) v s R u st ( 1 7 m s) Функция не аллоцирует объекты, единственная разница — в

if

нет () вокруг условия

{} обязательны

else if — особый синтаксис, нет dangling else problem

если нет блока else , значение — ()

let res = if condition1 { expr1; expr2 } else if condition2 { expr3 } else { expr4 };

77/96

Page 80: Лекция 1: Введение · Jav a ( 3 0 m s) v s R u st ( 1 7 m s) Функция не аллоцирует объекты, единственная разница — в

if

fn main() { if true { 92 // expected (), found integral variable } }

78/96

Page 81: Лекция 1: Введение · Jav a ( 3 0 m s) v s R u st ( 1 7 m s) Функция не аллоцирует объекты, единственная разница — в

if

fn main() { if true { 92; // ok! } }

79/96

Page 82: Лекция 1: Введение · Jav a ( 3 0 m s) v s R u st ( 1 7 m s) Функция не аллоцирует объекты, единственная разница — в

while

while condition { body // <- должно быть типа () } let x: () = while false {};

80/96

Page 83: Лекция 1: Введение · Jav a ( 3 0 m s) v s R u st ( 1 7 m s) Функция не аллоцирует объекты, единственная разница — в

break и continue

while true { if cond1 { continue; } if cond2 { break; } } 'outer: while cond1 { while cond2 { break 'outer; } }

81/96

Page 84: Лекция 1: Введение · Jav a ( 3 0 m s) v s R u st ( 1 7 m s) Функция не аллоцирует объекты, единственная разница — в

loopСпециальная конструкция для бесконечного цикла

loop {} и while true {} отличаютсяинформацией про поток управления

loop { body }

82/96

Page 85: Лекция 1: Введение · Jav a ( 3 0 m s) v s R u st ( 1 7 m s) Функция не аллоцирует объекты, единственная разница — в

loop

let uninit; while true { if condition { uninit = 92; break; } } pritnln!("{}", uninit); let init; loop { if condition { init = 92; break; } } pritnln!("{}", init); // ok

83/96

Page 86: Лекция 1: Введение · Jav a ( 3 0 m s) v s R u st ( 1 7 m s) Функция не аллоцирует объекты, единственная разница — в

loop

let init; if condition { init = 92; } else { loop {} } println!("{}", init); // ok!

84/96

Page 87: Лекция 1: Введение · Jav a ( 3 0 m s) v s R u st ( 1 7 m s) Функция не аллоцирует объекты, единственная разница — в

Гарантированная инициализация

в C/C++ доступ к неинициализированной переменной — UB

инициализация значением по умолчанию прячет баги

85/96

Page 88: Лекция 1: Введение · Jav a ( 3 0 m s) v s R u st ( 1 7 m s) Функция не аллоцирует объекты, единственная разница — в

!

ненаселённый тип

может выступать в роли любого другого типа

пока ещё не настоящий тип

let x: ! = loop {};

let x: u32 = loop {};

86/96

Page 89: Лекция 1: Введение · Jav a ( 3 0 m s) v s R u st ( 1 7 m s) Функция не аллоцирует объекты, единственная разница — в

panic!()Семейство макросов, возвращающих ! :

panic!("something went wrong") — для сигнализации обагах

unimplemented!() — плейсхолдер для ещё не написанногокода

unreachable!() — маркер для "невозможных" условий

if complex_condition { complex_logic } else { unimplemented!() }

87/96

Page 90: Лекция 1: Введение · Jav a ( 3 0 m s) v s R u st ( 1 7 m s) Функция не аллоцирует объекты, единственная разница — в

break со значением

let init: i32 = loop { if condition { break 92; } };

88/96

Page 91: Лекция 1: Введение · Jav a ( 3 0 m s) v s R u st ( 1 7 m s) Функция не аллоцирует объекты, единственная разница — в

for

Протокол итераторов — дальше в курсе

for x in vec![1, 2, 3] { println!("x = {}", x); } let xs = vec![1, 2, 3]; for i in 0..xs.len() { let x = xs[i]; pritnln!("x = ", x); }

89/96

Page 92: Лекция 1: Введение · Jav a ( 3 0 m s) v s R u st ( 1 7 m s) Функция не аллоцирует объекты, единственная разница — в

ranges

Пo lo..hi и lo.. можно итерироваться

let bounded = 0..10; let from = 0..; let to = ..10; let full = ..; for i in (0..10).step_by(2) { println!("i = {}", i); }

90/96

Page 93: Лекция 1: Введение · Jav a ( 3 0 m s) v s R u st ( 1 7 m s) Функция не аллоцирует объекты, единственная разница — в

Сопоставление с образцом

Материал следующей лекции

match read_input() { Ok(input) => process(input), Err(e) => handled_error(e), } if let Some(x) = optional_value { ... }

91/96

Page 94: Лекция 1: Введение · Jav a ( 3 0 m s) v s R u st ( 1 7 m s) Функция не аллоцирует объекты, единственная разница — в

Ещё раз о ;; превращает expression в statement После выражений-блоков ; не нужна:

{ if x == 0 { println!("zero"); } // statement { 0; } // statement if true { 92 } else { 62 } // expression! }

92/96

Page 95: Лекция 1: Введение · Jav a ( 3 0 m s) v s R u st ( 1 7 m s) Функция не аллоцирует объекты, единственная разница — в

Ещё раз о ;После let ; обязательна:

let s = if x > 0 { "positive" } else { "negative" };

93/96

Page 96: Лекция 1: Введение · Jav a ( 3 0 m s) v s R u st ( 1 7 m s) Функция не аллоцирует объекты, единственная разница — в

Два слова о функциях

типы параметров и результата обязательны

fn main {} == fn main() -> ()

тело функции — блок

return опционален

fn diverge() -> ! { loop {} }

fn hypot(x: f64, y: f64) -> f64 { let x_squared = x * x; let y_squared = y * y; (x_squared + y_squared).sqrt() }

94/96

Page 97: Лекция 1: Введение · Jav a ( 3 0 m s) v s R u st ( 1 7 m s) Функция не аллоцирует объекты, единственная разница — в

Quiz

Какой тип у x ?

fn foo() { let x = return; }

95/96

Page 98: Лекция 1: Введение · Jav a ( 3 0 m s) v s R u st ( 1 7 m s) Функция не аллоцирует объекты, единственная разница — в

Ссылкиhttps://www.rust-lang.org/

https://rustup.rs/

https://doc.rust-lang.org/book/

https://doc.rust-lang.org/rust-by-example/

https://doc.rust-lang.org/std/

У Rust превосходная документация, можно выучить язык покнижке.

96/96