// `first` и `second` выходят из области видимости и освобождаются
}
}
fn main() {
let rectangle = Rectangle {
// Статические методы вызываются двойными двоеточиями
p1: Point::origin(),
p2: Point::new(3.0, 4.0),
};
// Метод экземпляра вызывается с помощью оператора точка
// Обратите внимание, что первый аргумент `&self` неявно пропускается т.е.
// `rectangle.perimeter()` === `perimeter(&rectangle)`
println!("Rectangle perimeter: {}", rectangle.perimeter());
println!("Rectangle area: {}", rectangle.area());
let mut square = Rectangle {
p1: Point::origin(),
p2: Point::new(1.0, 1.0),
};
// Ошибка! `rectangle` неизменяемый, но этот метод нуждается в изменяемом
// объекте
//rectangle.translate(1.0, 0.0);
// ЗАДАНИЕ ^ Попробуйте удалить комментарий
// Хорошо, изменяемый объект может вызывать изменяемые методы
square.translate(1.0, 1.0);
let pair = Pair(Box::new(1), Box::new(2));
pair.destroy();
// Ошибка! `destroy` вызывает "съеденный" `pair`
//pair.destroy();
// ЗАДАНИЕ ^ Попробуйте удалить комментарий
}
הההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההה
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Замыкания
Замыкания в Rust, так же называемые лямбда, это функции, которые замыкают своё окружение. Для примера, замыкание, которое захватывает значение переменной x:
|val| val + x
Синтаксис и возможности замыканий делают их очень удобными для использования "на лету". Использование замыканий похоже на использование функций. Однако, тип входных и возвращаемых значений может быть выведен, а название аргумента должно быть указано.
Другие характеристики замыканий включают в себя:
• использование || вместо () для аргументов.
• опциональное ограничения тела функции ({}) для одного выражения (в противном случае обязательно).
• возможность захвата переменных за пределами окружения
fn main() {
// Инкремент с помощью замыкания и функции.
fn function (i: i32) -> i32 { i + 1 }
// Замыкания анонимны. Тут мы связываем их с ссылками
// Аннотация идентичны аннотации типов функции, но является опциональной
// как и оборачивания тела в `{}`. Эти безымянные функции
// назначены соответствующе названным переменным.
let closure_annotated = |i: i32| -> i32 { i + 1 };
let closure_inferred = |i | i + 1 ;
let i = 1;
// Вызов функции и замыкания.
println!("функция: {}", function(i));
println!("замыкание с указанием типа: {}", closure_annotated(i));
println!("замыкание с выводом типа: {}", closure_inferred(i));
// Замыкание не принимает аргументов, но возвращает `i32`.
// Тип возвращаемого значения выведен автоматически.
let one = || 1;
println!("замыкание, возвращающее один: {}", one());
}
הההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההה
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Захват
Замыкания довольно гибкие и делают всё, что требуется для работы с ними без дополнительных указаний. Это позволяет захватывать переменные перемещая их или заимствуя, в зависимости от необходимости. Замыкания могут захватывать переменные:
• по ссылке: &T
• по изменяемой ссылке: &mut T
• по значению: T
Преимущественно, они захватывают переменные по ссылке, если явно не указан другой способ.
fn main() {
use std::mem;
let color = "green";
// Замыкание для вывода `color`, которое немедленно заимствует (`&`)
// `color` и сохраняет замыкание в переменной `print`. color` будет оставаться
// заимствованным до тех пор, пока `print` используется.
//
// `println!` принимает аргументы по неизменяемым ссылкам, поэтому он не накладывает
// дополнительных ограничений.
let print = || println!("`color`: {}", color);
// Вызываем замыкание, использующее заимствование.
print();
// `color` может быть неизменяемо заимствован, так как замыкание
// держит только неизменяемую ссылку на `color`.
let _reborrow = &color;
print();
// Перемещение или перезанятие возможно после последнего использования `print`
let _color_moved = color;
let mut count = 0;
// Замыкание для увеличения `count` может принимать как `&mut count`, так и `count`,
// но использование `&mut count` менее ограничено, так что
// замыкание выбирает первый способ, т.е. немедленно заимствует `count`.
//
// inc` должен быть `mut`, поскольку внутри него хранится `&mut`.
// Таким образом, вызов замыкания изменяет его, что недопустимо без `mut`.
let mut inc = || {
count += 1;
println!("`count`: {}", count);
};
// Вызываем замыкание, использующее изменяемое заимствование.
inc();
// Замыкание продолжает изменяемо заимствовать `count` так как оно используется дальше.
// Попытка перезанять приведёт к ошибке.
// let _reborrow = &count;
// ^ TODO: попробуйте раскомментировать эту строку.
inc();
// Замыкание больше не заимствует `&mut count`. Так что теперь
// при перезаимствовании ошибок не будет.
let _count_reborrowed = &mut count;
// Некопируемый тип.