[Перевод] Rust на примерах. Часть 2
Это вторая часть из цикла статей по переводу книги «Rust by Example». Первую часть можно прочитать здесь.Продолжим?
СодержаниеВыражения Операторы ветвления Петли Цикл while Цикл for и функция range Функции 1. Выражения В Rust почти все фигурные скобки являются выражением, это значит, что они могут вернуть какой-то результат. Такое поведение не всегда нужно, чтобы ничего не возвращать добавьте; в конец.Выражения в блоке могут использоваться в качестве r-values значений, а последнее будет назначено как l-value.* Что такое Rvalue и Lvalue читайте здесь.
Но, если последнее выражение в блоке будет точкой с запятой, результат будет равен пустому кортежу: ().
fn main () { let x = 5u;
let y = { let x_squared = x * x; let x_cube = x_squared * x;
// `y` будет этим выражением x_cube + x_squared + x };
let z = { // Если в конце стоит точка с запятой, то выражение не // присваивается, вместо него переменная `z` будет содержать `()` 2 * x; };
println!(«x is {}», x); println!(«y is {}», y); println!(«z is {}», z); } 2. Операторы ветвления Ветвление if-else является C-подобным. В отличие от C, логическое условие не должно быть заключено в круглые скобки, а каждому условию необходимы фигурные скобки.if-else так же является выражением; и, из-за типобезопасности Rust, все ветви должны возвращать значение одного типа.
fn main () { let n = 5i;
if n < 0 { print!("{} is negative", n); } else if n > 0 { print!(»{} is positive», n); } else { print!(»{} is zero», n); }
let big_n = if n < 10 && n > -10 { println!(», and is a small number, increase ten-fold»);
// Это выражение возвращает `int` 10 * n } else { println!(», and is a big number, reduce by two»);
// Это выражение должно возвращать `int` n / 2 // ^ Попробуйте поставить точку с запятой };
println!(»{} → {}», n, big_n); } 3. Петли Ключевое слово loop в Rust создает бесконечный цикл (петлю).Оператор break позволяет выйти из петли в любое время, а continue пропускает оставшуюся часть итерации и начинает выполнение заново.
fn main () { let mut count = 0u;
println!(«Let’s count until infinity!»);
// Бесконечная петля loop { count += 1;
if count == 3 { println!(«three»);
// Пропустим оставшуюся часть этой итерации continue; }
println!(»{}», count);
if count == 5 { println!(«OK, that’s enough»);
// Выход из этой петли break; } } } 3.1 Вложенность и ярлыки Петли можно делать вложенными. В таких случаях они должны содержать какой-то ярлык 'label, а операторы break/continue писаться с этим ярлыком. fn main () { 'outer: loop { println!(«Entered the outer loop»);
'inner: loop { println!(«Entered the inner loop»);
// Выход из внутренней петли //break;
// Выход из внешней петли break 'outer; }
println!(«This point will never be reached»); }
println!(«Exited the outer loop»); } 4. Цикл while Тело цикла будет выполняться пока условие в while не будет истинно.Давайте напишем fizzbuzz используя цикл while.
fn main () { // Переменная для счетчика let mut n = 1u;
// Итерируем пока `n` меньше 101 while n < 101 { if n % 15 == 0 { println!("fizzbuzz"); } else if n % 3 == 0 { println!("fizz"); } else if n % 5 == 0 { println!("buzz"); } else { println!("{}", n); }
// Увеличиваем счетчик n += 1; } } 5. Цикл for и функция range Конструкцию for in можно использовать для перебора Iterator и генератора ленивых значений (подробнее позже). Функция range это один из наиболее распространенных итераторов. range (a, b) будет выдавать значения от a до b-1 изменяя шаг на единицу.Давайте напишем fizzbuzz используя for вместо while.
fn main () { // `n` будет принимать значения: 1, 2, …, 100 в каждой итерации for n in range (1u, 101) { if n % 15 == 0 { println!(«fizzbuzz»); } else if n % 3 == 0 { println!(«fizz»); } else if n % 5 == 0 { println!(«buzz»); } else { println!(»{}», n); } } } 6. Функции Функции объявляются при помощи ключевого слова fn. Аргументы аннотируются типами, как и переменные; и, если функция возвращает значение, возвращаемый тип должен быть указан после стрелки →.Последнее выражение в теле функции будет использовано как возвращаемое значение или можно использовать оператор return для раннего возврата значения из функции, даже из внутреннего цикла или условного оператора.
Перепишем fizzbuzz используя функции!
// Функция, которая возвращает булево значение fn is_divisible_by (lhs: uint, rhs: uint) → bool { // Некорректный входной параметр, сразу выходим из функции if rhs == 0 { return false; }
// Это выражение, так что ключевое слово `return` тут не нужно lhs % rhs == 0 }
// Функции, которые не возвращают значение, на самом деле возвращают тип `()` fn fizzbuzz (n: uint) → () { if is_divisible_by (n, 15) { println!(«fizzbuzz»); } else if is_divisible_by (n, 3) { println!(«fizz»); } else if is_divisible_by (n, 5) { println!(«buzz»); } else { println!(»{}», n); } }
// Если функция возвращает `()`, возвращаемый тип можно опустить fn fizzbuzz_to (n: uint) { for n in range (1, n + 1) { fizzbuzz (n); } }
fn main () { fizzbuzz_to (100); } 6.1 Неиспользуемые функции Компилятор обеспечивает dead_code lint, чтобы предупреждать о неиспользованных функциях. Можно добавить атрибут #[allow (dead_code)], чтобы отключить уведомление. fn used_function () {}
// `#[allow (dead_code)]` это атрибут, который отключает предупреждение `dead_code` #[allow (dead_code)] fn unused_function () {}
fn noisy_unused_function () {} // ИСПРАВЬТЕ ^ Добавьте атрибут, чтобы отключить предупреждение
fn main () { used_function (); } Обратите внимание, что в реальных программах, вы должны устранить «мертвый код». В этих примерах мы его используем для демонстрации.Заключение Присоединяйтесь к google-группе: Rust по-русски для получения дополнительной информации по этому языку.Можно помочь с переводом на Github: github.com/eg0r/rust-by-exampleВсе замечания, ошибки или неточности отправляйте мне в почту.