From 41055d177194e4bb50319a3cca6dd6ad54c463df Mon Sep 17 00:00:00 2001 From: funkill Date: Fri, 22 Sep 2023 13:51:05 +0000 Subject: [PATCH 1/5] Translate ch02-00-guessing-game-tutorial.md via GitLocalize --- .../src/ch02-00-guessing-game-tutorial.md | 42 ++++++------------- 1 file changed, 13 insertions(+), 29 deletions(-) diff --git a/rustbook-ru/src/ch02-00-guessing-game-tutorial.md b/rustbook-ru/src/ch02-00-guessing-game-tutorial.md index 49e17dedc..1f3ad1bb8 100644 --- a/rustbook-ru/src/ch02-00-guessing-game-tutorial.md +++ b/rustbook-ru/src/ch02-00-guessing-game-tutorial.md @@ -68,7 +68,7 @@ cd ../../.. {{#rustdoc_include ../listings/ch02-guessing-game-tutorial/listing-02-01/src/main.rs:io}} ``` -По умолчанию в Rust есть набор элементов, определённых в стандартной библиотеке, которые он добавляет в область видимости каждой программы. Этот набор называется *прелюдией*, и вы можете изучить его содержание [в документации стандартной библиотеки]. +По умолчанию в Rust есть набор элементов, определённых в стандартной библиотеке, которые он добавляет в область видимости каждой программы. Этот набор называется *прелюдией*, и вы можете изучить его содержание [в документации стандартной библиотеки](../std/prelude/index.html). Если тип, который требуется использовать, отсутствует в прелюдии, его нужно явно ввести в область видимости с помощью оператора `use`. Использование библиотеки `std::io` предоставляет ряд полезных функциональных возможностей, включая способность принимать пользовательский ввод. @@ -102,14 +102,14 @@ cd ../../.. let apples = 5; ``` -Эта строка создаёт новую переменную с именем `apples` и привязывает её к значению 5. В Rust переменные неизменяемы по умолчанию, то есть как только мы присвоим переменной значение, оно не изменится. Мы подробно обсудим эту концепцию в разделе ["Переменные и изменчивость".] в главе 3. Чтобы сделать переменную изменяемой, мы добавляем `mut` перед её именем: +Эта строка создаёт новую переменную с именем `apples` и привязывает её к значению 5. В Rust переменные неизменяемы по умолчанию, то есть как только мы присвоим переменной значение, оно не изменится. Мы подробно обсудим эту концепцию в разделе ["Переменные и изменчивость".](ch03-01-variables-and-mutability.html#variables-and-mutability) в главе 3. Чтобы сделать переменную изменяемой, мы добавляем `mut` перед её именем: ```rust,ignore let apples = 5; // неизменяемая let mut bananas = 5; // изменяемая ``` -> Примечание: сочетание знаков `//` начинает комментарий, который продолжается до конца строки. Rust игнорирует всё, что находится в комментариях. Мы обсудим комментарии более подробно в [Главе 3]. +> Примечание: сочетание знаков `//` начинает комментарий, который продолжается до конца строки. Rust игнорирует всё, что находится в комментариях. Мы обсудим комментарии более подробно в [Главе 3](ch03-04-comments.html). > Возвращаясь к программе игры "Угадайка" — теперь вы знаете, что `let mut guess` предоставит изменяемую переменную с именем `guess`. Знак равенства (`=`) сообщает Rust, что сейчас нужно связать что-то с этой переменной. Справа от знака равенства находится значение, связанное с `guess`, которое является результатом вызова функции `String::new`, возвращающей новый экземпляр `String`. `String` — это тип строки, предоставляемый стандартной библиотекой, который является расширяемым фрагментом текста в кодировке UTF-8. @@ -126,9 +126,9 @@ let mut bananas = 5; // изменяемая {{#rustdoc_include ../listings/ch02-guessing-game-tutorial/listing-02-01/src/main.rs:read}} ``` -Если бы мы не импортировали библиотеку `io` с помощью `use std::io` в начале программы, мы все равно могли бы использовать эту функцию, записав её вызов как `std::io::stdin`. Функция `stdin` возвращает экземпляр [`std::io::Stdin`], который является типом, представляющим дескриптор стандартного ввода для вашего терминала. +Если бы мы не импортировали библиотеку `io` с помощью `use std::io` в начале программы, мы все равно могли бы использовать эту функцию, записав её вызов как `std::io::stdin`. Функция `stdin` возвращает экземпляр [`std::io::Stdin`](../std/io/struct.Stdin.html), который является типом, представляющим дескриптор стандартного ввода для вашего терминала. -Далее строка `.read_line(&mut guess)` вызывает метод [`read_line`] на дескрипторе стандартного ввода для получения ввода от пользователя. Мы также передаём `&mut guess` в качестве аргумента `read_line`, сообщая ему, в какой строке хранить пользовательский ввод. Главная задача `read_line` — принять все, что пользователь вводит в стандартный ввод, и сложить это в строку (не переписывая её содержимое), поэтому мы передаём эту строку в качестве аргумента. Строковый аргумент должен быть изменяемым, чтобы метод мог изменить содержимое строки. +Далее строка `.read_line(&mut guess)` вызывает метод [`read_line`](../std/io/struct.Stdin.html#method.read_line) на дескрипторе стандартного ввода для получения ввода от пользователя. Мы также передаём `&mut guess` в качестве аргумента `read_line`, сообщая ему, в какой строке хранить пользовательский ввод. Главная задача `read_line` — принять все, что пользователь вводит в стандартный ввод, и сложить это в строку (не переписывая её содержимое), поэтому мы передаём эту строку в качестве аргумента. Строковый аргумент должен быть изменяемым, чтобы метод мог изменить содержимое строки. Символ `&` указывает, что этот аргумент является *ссылкой*, которая предоставляет возможность нескольким частям вашего кода получить доступ к одному фрагменту данных без необходимости копировать эти данные в память несколько раз. Ссылки — это сложная функциональная возможность, а одним из главных преимуществ Rust является безопасность и простота использования ссылок. Чтобы дописать эту программу, вам не понадобится знать много таких подробностей. Пока вам достаточно знать, что ссылки, как и переменные, по умолчанию неизменяемы. Соответственно, чтобы сделать её изменяемой, нужно написать `&mut guess`, а не `&guess`. (В главе 4 ссылки будут описаны более подробно). @@ -152,13 +152,13 @@ io::stdin().read_line(&mut guess).expect("Failed to read line"); Однако одну длинную строку трудно читать, поэтому лучше разделить её. При вызове метода с помощью синтаксиса `.method_name()` часто целесообразно вводить новую строку и другие пробельные символы, чтобы разбить длинные строки. Теперь давайте обсудим, что делает эта строка. -Как упоминалось ранее, `read_line` помещает всё, что вводит пользователь, в строку, которую мы ему передаём, но также возвращает значение `Result`. `Result` — это [*перечисление*], часто называемое *enum*, то есть тип, который может находиться в одном из нескольких возможных состояний. Мы называем каждое такое состояние *вариантом*. +Как упоминалось ранее, `read_line` помещает всё, что вводит пользователь, в строку, которую мы ему передаём, но также возвращает значение `Result`. `Result` — это [*перечисление*](ch06-00-enums.html), часто называемое *enum*, то есть тип, который может находиться в одном из нескольких возможных состояний. Мы называем каждое такое состояние *вариантом*. В [Главе 6](ch06-00-enums.html) рассмотрим перечисления более подробно. Задачей типов `Result` является кодирование информации для обработки ошибок. Вариантами `Result` являются `Ok` и `Err`. Вариант `Ok` указывает, что операция завершилась успешно, а внутри `Ok` находится успешно сгенерированное значение. Вариант `Err` означает, что операция не удалась, а `Err` содержит информацию о причинах неудачи. -Значения типа `Result`, как и значения любого типа, имеют определённые для них методы. У экземпляра `Result` есть [метод `expect`], который можно вызвать. Если этот экземпляр `Result` является значением `Err`, `expect` вызовет сбой программы и отобразит сообщение, которое вы передали в качестве аргумента. Если метод `read_line` возвращает `Err`, то это, скорее всего, результат ошибки базовой операционной системы. Если экземпляр `Result` является значением `Ok`, `expect` возьмёт возвращаемое значение, которое удерживает `Ok`, и вернёт вам только это значение, чтобы вы могли его использовать далее. В данном случае это значение представляет собой количество байтов, введённых пользователем. +Значения типа `Result`, как и значения любого типа, имеют определённые для них методы. У экземпляра `Result` есть [метод `expect`](../std/result/enum.Result.html#method.expect), который можно вызвать. Если этот экземпляр `Result` является значением `Err`, `expect` вызовет сбой программы и отобразит сообщение, которое вы передали в качестве аргумента. Если метод `read_line` возвращает `Err`, то это, скорее всего, результат ошибки базовой операционной системы. Если экземпляр `Result` является значением `Ok`, `expect` возьмёт возвращаемое значение, которое удерживает `Ok`, и вернёт вам только это значение, чтобы вы могли его использовать далее. В данном случае это значение представляет собой количество байтов, введённых пользователем. Если не вызвать `expect`, программа скомпилируется, но будет получено предупреждение: @@ -168,7 +168,7 @@ io::stdin().read_line(&mut guess).expect("Failed to read line"); Rust предупреждает о неиспользованном значении `Result`, возвращаемого из `read_line`, показывая, что программа не учла возможность возникновения ошибки. -Правильный способ убрать предупреждение — это написать обработку ошибок, но в нашем случае мы просто хотим аварийно завершить программу при возникновении проблемы, поэтому используем `expect`. О способах восстановления после ошибок вы узнаете в [главе 9]. +Правильный способ убрать предупреждение — это написать обработку ошибок, но в нашем случае мы просто хотим аварийно завершить программу при возникновении проблемы, поэтому используем `expect`. О способах восстановления после ошибок вы узнаете в [главе 9](ch09-02-recoverable-errors-with-result.html). ### Вывод значений с помощью заполнителей `println!` @@ -234,7 +234,7 @@ You guessed: 6 {{#include ../listings/ch02-guessing-game-tutorial/listing-02-02/Cargo.toml:8:}} ``` -В файле *Cargo.toml* всё, что следует за заголовком, является частью этой секции, которая продолжается до тех пор, пока не начнётся следующая. В `[dependencies]` вы сообщаете Cargo, от каких внешних крейтов зависит ваш проект и какие версии этих крейтов вам нужны. В этом случае мы указываем крейт `rand` со спецификатором семантической версии `0.8.5`. Cargo понимает [семантическое версионирование] (иногда называемое *SemVer*), которое является стандартом для описания версий. Число `0.8.5` на самом деле является сокращением от `^0.8.5`, что означает любую версию не ниже 0.8.5, но ниже 0.9.0. +В файле *Cargo.toml* всё, что следует за заголовком, является частью этой секции, которая продолжается до тех пор, пока не начнётся следующая. В `[dependencies]` вы сообщаете Cargo, от каких внешних крейтов зависит ваш проект и какие версии этих крейтов вам нужны. В этом случае мы указываем крейт `rand` со спецификатором семантической версии `0.8.5`. Cargo понимает [семантическое версионирование](http://semver.org) (иногда называемое *SemVer*), которое является стандартом для описания версий. Число `0.8.5` на самом деле является сокращением от `^0.8.5`, что означает любую версию не ниже 0.8.5, но ниже 0.9.0. Cargo рассчитывает, что эти версии имеют общедоступное API, совместимое с версией 0.8.5, и вы получите последние версии исправлений, которые по-прежнему будут компилироваться с кодом из этой главы. Не гарантируется, что версия 0.9.0 или выше будет иметь тот же API, что и в следующих примерах. @@ -271,7 +271,7 @@ $ cargo build Вы можете увидеть другие номера версий (но все они будут совместимы с кодом благодаря SemVer), другие строки (в зависимости от операционной системы), а также строки могут быть расположены в другом порядке. -Когда мы включаем внешнюю зависимость, Cargo берет последние версии всего, что нужно этой зависимости, из *реестра (registry)*, который является копией данных с [Crates.io]. Crates.io — это место, где участники экосистемы Rust размещают свои проекты с открытым исходным кодом для использования другими. +Когда мы включаем внешнюю зависимость, Cargo берет последние версии всего, что нужно этой зависимости, из *реестра (registry)*, который является копией данных с [Crates.io](https://crates.io/). Crates.io — это место, где участники экосистемы Rust размещают свои проекты с открытым исходным кодом для использования другими. После обновления реестра Cargo проверяет раздел `[dependencies]` и загружает все указанные в списке пакеты, которые ещё не были загружены. В нашем случае, хотя мы указали только `rand` в качестве зависимости, Cargo также захватил другие пакеты, от которых зависит работа `rand`. После загрузки пакетов Rust компилирует их, а затем компилирует проект с имеющимися зависимостями. @@ -323,7 +323,7 @@ rand = "0.9.0" В следующий раз, при запуске `cargo build`, Cargo обновит реестр доступных пакетов и пересмотрит ваши требования к `rand` в соответствии с новой версией, которую вы указали. -Можно много рассказать про [Cargo] и [его экосистему] которые мы обсудим в главе 14, сейчас это все что вам нужно знать. Cargo позволяет очень легко повторно использовать библиотеки, поэтому Rust разработчики имеют возможность писать меньшие проекты, которые скомпонованы из многих пакетов. +Можно много рассказать про [Cargo](http://doc.crates.io) и [его экосистему](http://doc.crates.io/crates-io.html) которые мы обсудим в главе 14, сейчас это все что вам нужно знать. Cargo позволяет очень легко повторно использовать библиотеки, поэтому Rust разработчики имеют возможность писать меньшие проекты, которые скомпонованы из многих пакетов. ### Генерация случайного числа @@ -392,7 +392,7 @@ You guessed: 5 Сначала добавим ещё один оператор `use`, который вводит тип с именем `std::cmp::Ordering` в область видимости из стандартной библиотеки. Тип `Ordering` является ещё одним перечислением и имеет варианты `Less`, `Greater` и `Equal`. Это три возможных исхода при сравнении двух величин. -После чего ниже добавляем пять новых строк, использующих тип `Ordering`. Метод `cmp` сравнивает два значения и может вызываться для всего, что можно сравнить. Он принимает ссылку на все, что требуется сравнить: здесь сравнивается `guess` с `secret_number`. В результате возвращается вариант перечисления `Ordering`, которое мы ввели в область видимости с помощью оператора `use`. Для принятия решения о том, что делать дальше, мы используем выражение [`match`], определяющее, какой вариант Ordering был возвращён из вызова `cmp` со значениями `guess` и `secret_number`. +После чего ниже добавляем пять новых строк, использующих тип `Ordering`. Метод `cmp` сравнивает два значения и может вызываться для всего, что можно сравнить. Он принимает ссылку на все, что требуется сравнить: здесь сравнивается `guess` с `secret_number`. В результате возвращается вариант перечисления `Ordering`, которое мы ввели в область видимости с помощью оператора `use`. Для принятия решения о том, что делать дальше, мы используем выражение [`match`](ch06-02-match.html), определяющее, какой вариант Ordering был возвращён из вызова `cmp` со значениями `guess` и `secret_number`. Выражение `match` состоит из *веток (arms)*. Ветка состоит из *шаблона* для сопоставления и кода, который будет запущен, если значение, переданное в `match`, соответствует шаблону этой ветки. Rust принимает значение, заданное `match`, и по очереди просматривает шаблон каждой ветки. Шаблоны и конструкция `match` — это мощные возможности Rust, позволяющие выразить множество ситуаций, с которыми может столкнуться ваш код, и гарантировать их обработку. Эти возможности будут подробно раскрыты в главе 6 и главе 18 соответственно. @@ -431,7 +431,7 @@ let guess: u32 = guess.trim().parse().expect("Please type a number!"); Мы связываем эту новую переменную с выражением `guess.trim().parse()`. Переменная `guess` в этом выражении относится к исходной переменной `guess`, которая содержала входные данные в виде строки. Метод `trim` на экземпляре `String` удалит любые пробельные символы в начале и конце строки для того, чтобы мы могли сопоставить строку с `u32`, который содержит только числовые данные. Пользователь должен нажать enter, чтобы выполнить `read_line` и ввести свою догадку, при этом в строку добавится символ новой строки. Например, если пользователь набирает 5 и нажимает enter, `guess` будет выглядеть так: `5\n`. Символ `\n` означает "новая строка". (В Windows нажатие enter сопровождается возвратом каретки и новой строкой, `\r\n`). Метод `trim` убирает `\n` или `\r\n`, оставляя только `5`. -Метод [`parse` строк] преобразует строку в другой тип. Здесь мы используем его для преобразования строки в число. Нам нужно сообщить Rust точный числовой тип, который мы хотим получить, используя `let guess: u32`. Двоеточие ( `:` ) после `guess` говорит Rust, что мы аннотируем тип переменной. В Rust есть несколько встроенных числовых типов; `u32`, показанный здесь, представляет собой 32-битное целое число без знака. Это хороший выбор по умолчанию для небольшого положительного числа. Вы узнаете о других типах чисел в главе 3. +Метод [`parse` строк](../std/primitive.str.html#method.parse) преобразует строку в другой тип. Здесь мы используем его для преобразования строки в число. Нам нужно сообщить Rust точный числовой тип, который мы хотим получить, используя `let guess: u32`. Двоеточие ( `:` ) после `guess` говорит Rust, что мы аннотируем тип переменной. В Rust есть несколько встроенных числовых типов; `u32`, показанный здесь, представляет собой 32-битное целое число без знака. Это хороший выбор по умолчанию для небольшого положительного числа. Вы узнаете о других типах чисел в главе 3. Кроме того, аннотация u32 в этом примере программы и сравнение с secret_number означает, что Rust сделает вывод, что secret_number должен быть u32. Итак, теперь сравнение будет между двумя значениями одного типа! @@ -591,19 +591,3 @@ You win! ## Заключение Этот проект — практический способ познакомить вас со многими новыми концепциями Rust: `let`, `match`, функции, использование внешних крейтов и многое другое. В следующих нескольких главах вы изучите эти концепции более подробно. Глава 3 охватывает понятия, которые есть в большинстве языков программирования, такие как переменные, типы данных и функции, и показывает, как использовать их в Rust. В главе 4 рассматривается владение — особенность, которая отличает Rust от других языков. В главе 5 обсуждаются структуры и синтаксис методов, а в главе 6 объясняется, как работают перечисления. - - -[в документации стандартной библиотеки]: ../std/prelude/index.html -["Переменные и изменчивость".]: ch03-01-variables-and-mutability.html#variables-and-mutability -[Главе 3]: ch03-04-comments.html -[`std::io::Stdin`]: ../std/io/struct.Stdin.html -[`read_line`]: ../std/io/struct.Stdin.html#method.read_line -[*перечисление*]: ch06-00-enums.html -[метод `expect`]: ../std/result/enum.Result.html#method.expect -[главе 9]: ch09-02-recoverable-errors-with-result.html -[семантическое версионирование]: http://semver.org -[Crates.io]: https://crates.io/ -[Cargo]: http://doc.crates.io -[его экосистему]: http://doc.crates.io/crates-io.html -[`match`]: ch06-02-match.html -[`parse` строк]: ../std/primitive.str.html#method.parse \ No newline at end of file From 539b2aa3645678b25befed5a4c22699c61885539 Mon Sep 17 00:00:00 2001 From: Roman Ponomarev Date: Fri, 22 Sep 2023 13:51:05 +0000 Subject: [PATCH 2/5] Translate ch02-00-guessing-game-tutorial.md via GitLocalize From af5bc5b544f2d8b4bd108bd6faff6bd56dc2747e Mon Sep 17 00:00:00 2001 From: Yuriy Larin Date: Fri, 22 Sep 2023 13:51:06 +0000 Subject: [PATCH 3/5] Translate ch02-00-guessing-game-tutorial.md via GitLocalize From 660e59c54d8831c0bf958f6149f241c3a65c3e2a Mon Sep 17 00:00:00 2001 From: Alexander Andreev Date: Fri, 22 Sep 2023 13:51:06 +0000 Subject: [PATCH 4/5] Translate ch02-00-guessing-game-tutorial.md via GitLocalize From 62ec671d513e0ef751220dc7f7da06f5746933ba Mon Sep 17 00:00:00 2001 From: Alexander Date: Fri, 22 Sep 2023 13:51:07 +0000 Subject: [PATCH 5/5] Translate ch02-00-guessing-game-tutorial.md via GitLocalize --- .../src/ch02-00-guessing-game-tutorial.md | 44 +++++++++++++------ 1 file changed, 30 insertions(+), 14 deletions(-) diff --git a/rustbook-ru/src/ch02-00-guessing-game-tutorial.md b/rustbook-ru/src/ch02-00-guessing-game-tutorial.md index 1f3ad1bb8..7874356ff 100644 --- a/rustbook-ru/src/ch02-00-guessing-game-tutorial.md +++ b/rustbook-ru/src/ch02-00-guessing-game-tutorial.md @@ -68,7 +68,7 @@ cd ../../.. {{#rustdoc_include ../listings/ch02-guessing-game-tutorial/listing-02-01/src/main.rs:io}} ``` -По умолчанию в Rust есть набор элементов, определённых в стандартной библиотеке, которые он добавляет в область видимости каждой программы. Этот набор называется *прелюдией*, и вы можете изучить его содержание [в документации стандартной библиотеки](../std/prelude/index.html). +По умолчанию в Rust есть набор элементов, определённых в стандартной библиотеке, которые он добавляет в область видимости каждой программы. Этот набор называется *прелюдией*, и вы можете изучить его содержание [в документации стандартной библиотеки]. Если тип, который требуется использовать, отсутствует в прелюдии, его нужно явно ввести в область видимости с помощью оператора `use`. Использование библиотеки `std::io` предоставляет ряд полезных функциональных возможностей, включая способность принимать пользовательский ввод. @@ -102,14 +102,14 @@ cd ../../.. let apples = 5; ``` -Эта строка создаёт новую переменную с именем `apples` и привязывает её к значению 5. В Rust переменные неизменяемы по умолчанию, то есть как только мы присвоим переменной значение, оно не изменится. Мы подробно обсудим эту концепцию в разделе ["Переменные и изменчивость".](ch03-01-variables-and-mutability.html#variables-and-mutability) в главе 3. Чтобы сделать переменную изменяемой, мы добавляем `mut` перед её именем: +Эта строка создаёт новую переменную с именем `apples` и привязывает её к значению 5. В Rust переменные неизменяемы по умолчанию, то есть как только мы присвоим переменной значение, оно не изменится. Мы подробно обсудим эту концепцию в разделе ["Переменные и изменчивость".] в главе 3. Чтобы сделать переменную изменяемой, мы добавляем `mut` перед её именем: ```rust,ignore let apples = 5; // неизменяемая let mut bananas = 5; // изменяемая ``` -> Примечание: сочетание знаков `//` начинает комментарий, который продолжается до конца строки. Rust игнорирует всё, что находится в комментариях. Мы обсудим комментарии более подробно в [Главе 3](ch03-04-comments.html). +> Примечание: сочетание знаков `//` начинает комментарий, который продолжается до конца строки. Rust игнорирует всё, что находится в комментариях. Мы обсудим комментарии более подробно в [Главе 3]. > Возвращаясь к программе игры "Угадайка" — теперь вы знаете, что `let mut guess` предоставит изменяемую переменную с именем `guess`. Знак равенства (`=`) сообщает Rust, что сейчас нужно связать что-то с этой переменной. Справа от знака равенства находится значение, связанное с `guess`, которое является результатом вызова функции `String::new`, возвращающей новый экземпляр `String`. `String` — это тип строки, предоставляемый стандартной библиотекой, который является расширяемым фрагментом текста в кодировке UTF-8. @@ -126,9 +126,9 @@ let mut bananas = 5; // изменяемая {{#rustdoc_include ../listings/ch02-guessing-game-tutorial/listing-02-01/src/main.rs:read}} ``` -Если бы мы не импортировали библиотеку `io` с помощью `use std::io` в начале программы, мы все равно могли бы использовать эту функцию, записав её вызов как `std::io::stdin`. Функция `stdin` возвращает экземпляр [`std::io::Stdin`](../std/io/struct.Stdin.html), который является типом, представляющим дескриптор стандартного ввода для вашего терминала. +Если бы мы не импортировали библиотеку `io` с помощью `use std::io` в начале программы, мы все равно могли бы использовать эту функцию, записав её вызов как `std::io::stdin`. Функция `stdin` возвращает экземпляр [`std::io::Stdin`], который является типом, представляющим дескриптор стандартного ввода для вашего терминала. -Далее строка `.read_line(&mut guess)` вызывает метод [`read_line`](../std/io/struct.Stdin.html#method.read_line) на дескрипторе стандартного ввода для получения ввода от пользователя. Мы также передаём `&mut guess` в качестве аргумента `read_line`, сообщая ему, в какой строке хранить пользовательский ввод. Главная задача `read_line` — принять все, что пользователь вводит в стандартный ввод, и сложить это в строку (не переписывая её содержимое), поэтому мы передаём эту строку в качестве аргумента. Строковый аргумент должен быть изменяемым, чтобы метод мог изменить содержимое строки. +Далее строка `.read_line(&mut guess)` вызывает метод [`read_line`] на дескрипторе стандартного ввода для получения ввода от пользователя. Мы также передаём `&mut guess` в качестве аргумента `read_line`, сообщая ему, в какой строке хранить пользовательский ввод. Главная задача `read_line` — принять все, что пользователь вводит в стандартный ввод, и сложить это в строку (не переписывая её содержимое), поэтому мы передаём эту строку в качестве аргумента. Строковый аргумент должен быть изменяемым, чтобы метод мог изменить содержимое строки. Символ `&` указывает, что этот аргумент является *ссылкой*, которая предоставляет возможность нескольким частям вашего кода получить доступ к одному фрагменту данных без необходимости копировать эти данные в память несколько раз. Ссылки — это сложная функциональная возможность, а одним из главных преимуществ Rust является безопасность и простота использования ссылок. Чтобы дописать эту программу, вам не понадобится знать много таких подробностей. Пока вам достаточно знать, что ссылки, как и переменные, по умолчанию неизменяемы. Соответственно, чтобы сделать её изменяемой, нужно написать `&mut guess`, а не `&guess`. (В главе 4 ссылки будут описаны более подробно). @@ -152,13 +152,13 @@ io::stdin().read_line(&mut guess).expect("Failed to read line"); Однако одну длинную строку трудно читать, поэтому лучше разделить её. При вызове метода с помощью синтаксиса `.method_name()` часто целесообразно вводить новую строку и другие пробельные символы, чтобы разбить длинные строки. Теперь давайте обсудим, что делает эта строка. -Как упоминалось ранее, `read_line` помещает всё, что вводит пользователь, в строку, которую мы ему передаём, но также возвращает значение `Result`. `Result` — это [*перечисление*](ch06-00-enums.html), часто называемое *enum*, то есть тип, который может находиться в одном из нескольких возможных состояний. Мы называем каждое такое состояние *вариантом*. +Как упоминалось ранее, `read_line` помещает всё, что вводит пользователь, в строку, которую мы ему передаём, но также возвращает значение `Result`. `Result` — это [*перечисление*], часто называемое *enum*, то есть тип, который может находиться в одном из нескольких возможных состояний. Мы называем каждое такое состояние *вариантом*. В [Главе 6](ch06-00-enums.html) рассмотрим перечисления более подробно. Задачей типов `Result` является кодирование информации для обработки ошибок. Вариантами `Result` являются `Ok` и `Err`. Вариант `Ok` указывает, что операция завершилась успешно, а внутри `Ok` находится успешно сгенерированное значение. Вариант `Err` означает, что операция не удалась, а `Err` содержит информацию о причинах неудачи. -Значения типа `Result`, как и значения любого типа, имеют определённые для них методы. У экземпляра `Result` есть [метод `expect`](../std/result/enum.Result.html#method.expect), который можно вызвать. Если этот экземпляр `Result` является значением `Err`, `expect` вызовет сбой программы и отобразит сообщение, которое вы передали в качестве аргумента. Если метод `read_line` возвращает `Err`, то это, скорее всего, результат ошибки базовой операционной системы. Если экземпляр `Result` является значением `Ok`, `expect` возьмёт возвращаемое значение, которое удерживает `Ok`, и вернёт вам только это значение, чтобы вы могли его использовать далее. В данном случае это значение представляет собой количество байтов, введённых пользователем. +Значения типа `Result`, как и значения любого типа, имеют определённые для них методы. У экземпляра `Result` есть [метод `expect`], который можно вызвать. Если этот экземпляр `Result` является значением `Err`, `expect` вызовет сбой программы и отобразит сообщение, которое вы передали в качестве аргумента. Если метод `read_line` возвращает `Err`, то это, скорее всего, результат ошибки базовой операционной системы. Если экземпляр `Result` является значением `Ok`, `expect` возьмёт возвращаемое значение, которое удерживает `Ok`, и вернёт вам только это значение, чтобы вы могли его использовать далее. В данном случае это значение представляет собой количество байтов, введённых пользователем. Если не вызвать `expect`, программа скомпилируется, но будет получено предупреждение: @@ -168,7 +168,7 @@ io::stdin().read_line(&mut guess).expect("Failed to read line"); Rust предупреждает о неиспользованном значении `Result`, возвращаемого из `read_line`, показывая, что программа не учла возможность возникновения ошибки. -Правильный способ убрать предупреждение — это написать обработку ошибок, но в нашем случае мы просто хотим аварийно завершить программу при возникновении проблемы, поэтому используем `expect`. О способах восстановления после ошибок вы узнаете в [главе 9](ch09-02-recoverable-errors-with-result.html). +Правильный способ убрать предупреждение — это написать обработку ошибок, но в нашем случае мы просто хотим аварийно завершить программу при возникновении проблемы, поэтому используем `expect`. О способах восстановления после ошибок вы узнаете в [главе 9]. ### Вывод значений с помощью заполнителей `println!` @@ -234,7 +234,7 @@ You guessed: 6 {{#include ../listings/ch02-guessing-game-tutorial/listing-02-02/Cargo.toml:8:}} ``` -В файле *Cargo.toml* всё, что следует за заголовком, является частью этой секции, которая продолжается до тех пор, пока не начнётся следующая. В `[dependencies]` вы сообщаете Cargo, от каких внешних крейтов зависит ваш проект и какие версии этих крейтов вам нужны. В этом случае мы указываем крейт `rand` со спецификатором семантической версии `0.8.5`. Cargo понимает [семантическое версионирование](http://semver.org) (иногда называемое *SemVer*), которое является стандартом для описания версий. Число `0.8.5` на самом деле является сокращением от `^0.8.5`, что означает любую версию не ниже 0.8.5, но ниже 0.9.0. +В файле *Cargo.toml* всё, что следует за заголовком, является частью этой секции, которая продолжается до тех пор, пока не начнётся следующая. В `[dependencies]` вы сообщаете Cargo, от каких внешних крейтов зависит ваш проект и какие версии этих крейтов вам нужны. В этом случае мы указываем крейт `rand` со спецификатором семантической версии `0.8.5`. Cargo понимает [семантическое версионирование] (иногда называемое *SemVer*), которое является стандартом для описания версий. Число `0.8.5` на самом деле является сокращением от `^0.8.5`, что означает любую версию не ниже 0.8.5, но ниже 0.9.0. Cargo рассчитывает, что эти версии имеют общедоступное API, совместимое с версией 0.8.5, и вы получите последние версии исправлений, которые по-прежнему будут компилироваться с кодом из этой главы. Не гарантируется, что версия 0.9.0 или выше будет иметь тот же API, что и в следующих примерах. @@ -271,7 +271,7 @@ $ cargo build Вы можете увидеть другие номера версий (но все они будут совместимы с кодом благодаря SemVer), другие строки (в зависимости от операционной системы), а также строки могут быть расположены в другом порядке. -Когда мы включаем внешнюю зависимость, Cargo берет последние версии всего, что нужно этой зависимости, из *реестра (registry)*, который является копией данных с [Crates.io](https://crates.io/). Crates.io — это место, где участники экосистемы Rust размещают свои проекты с открытым исходным кодом для использования другими. +Когда мы включаем внешнюю зависимость, Cargo берет последние версии всего, что нужно этой зависимости, из *реестра (registry)*, который является копией данных с [Crates.io]. Crates.io — это место, где участники экосистемы Rust размещают свои проекты с открытым исходным кодом для использования другими. После обновления реестра Cargo проверяет раздел `[dependencies]` и загружает все указанные в списке пакеты, которые ещё не были загружены. В нашем случае, хотя мы указали только `rand` в качестве зависимости, Cargo также захватил другие пакеты, от которых зависит работа `rand`. После загрузки пакетов Rust компилирует их, а затем компилирует проект с имеющимися зависимостями. @@ -323,7 +323,7 @@ rand = "0.9.0" В следующий раз, при запуске `cargo build`, Cargo обновит реестр доступных пакетов и пересмотрит ваши требования к `rand` в соответствии с новой версией, которую вы указали. -Можно много рассказать про [Cargo](http://doc.crates.io) и [его экосистему](http://doc.crates.io/crates-io.html) которые мы обсудим в главе 14, сейчас это все что вам нужно знать. Cargo позволяет очень легко повторно использовать библиотеки, поэтому Rust разработчики имеют возможность писать меньшие проекты, которые скомпонованы из многих пакетов. +Можно много рассказать про [Cargo] и [его экосистему] которые мы обсудим в главе 14, сейчас это все что вам нужно знать. Cargo позволяет очень легко повторно использовать библиотеки, поэтому Rust разработчики имеют возможность писать меньшие проекты, которые скомпонованы из многих пакетов. ### Генерация случайного числа @@ -392,7 +392,7 @@ You guessed: 5 Сначала добавим ещё один оператор `use`, который вводит тип с именем `std::cmp::Ordering` в область видимости из стандартной библиотеки. Тип `Ordering` является ещё одним перечислением и имеет варианты `Less`, `Greater` и `Equal`. Это три возможных исхода при сравнении двух величин. -После чего ниже добавляем пять новых строк, использующих тип `Ordering`. Метод `cmp` сравнивает два значения и может вызываться для всего, что можно сравнить. Он принимает ссылку на все, что требуется сравнить: здесь сравнивается `guess` с `secret_number`. В результате возвращается вариант перечисления `Ordering`, которое мы ввели в область видимости с помощью оператора `use`. Для принятия решения о том, что делать дальше, мы используем выражение [`match`](ch06-02-match.html), определяющее, какой вариант Ordering был возвращён из вызова `cmp` со значениями `guess` и `secret_number`. +После чего ниже добавляем пять новых строк, использующих тип `Ordering`. Метод `cmp` сравнивает два значения и может вызываться для всего, что можно сравнить. Он принимает ссылку на все, что требуется сравнить: здесь сравнивается `guess` с `secret_number`. В результате возвращается вариант перечисления `Ordering`, которое мы ввели в область видимости с помощью оператора `use`. Для принятия решения о том, что делать дальше, мы используем выражение [`match`], определяющее, какой вариант Ordering был возвращён из вызова `cmp` со значениями `guess` и `secret_number`. Выражение `match` состоит из *веток (arms)*. Ветка состоит из *шаблона* для сопоставления и кода, который будет запущен, если значение, переданное в `match`, соответствует шаблону этой ветки. Rust принимает значение, заданное `match`, и по очереди просматривает шаблон каждой ветки. Шаблоны и конструкция `match` — это мощные возможности Rust, позволяющие выразить множество ситуаций, с которыми может столкнуться ваш код, и гарантировать их обработку. Эти возможности будут подробно раскрыты в главе 6 и главе 18 соответственно. @@ -431,7 +431,7 @@ let guess: u32 = guess.trim().parse().expect("Please type a number!"); Мы связываем эту новую переменную с выражением `guess.trim().parse()`. Переменная `guess` в этом выражении относится к исходной переменной `guess`, которая содержала входные данные в виде строки. Метод `trim` на экземпляре `String` удалит любые пробельные символы в начале и конце строки для того, чтобы мы могли сопоставить строку с `u32`, который содержит только числовые данные. Пользователь должен нажать enter, чтобы выполнить `read_line` и ввести свою догадку, при этом в строку добавится символ новой строки. Например, если пользователь набирает 5 и нажимает enter, `guess` будет выглядеть так: `5\n`. Символ `\n` означает "новая строка". (В Windows нажатие enter сопровождается возвратом каретки и новой строкой, `\r\n`). Метод `trim` убирает `\n` или `\r\n`, оставляя только `5`. -Метод [`parse` строк](../std/primitive.str.html#method.parse) преобразует строку в другой тип. Здесь мы используем его для преобразования строки в число. Нам нужно сообщить Rust точный числовой тип, который мы хотим получить, используя `let guess: u32`. Двоеточие ( `:` ) после `guess` говорит Rust, что мы аннотируем тип переменной. В Rust есть несколько встроенных числовых типов; `u32`, показанный здесь, представляет собой 32-битное целое число без знака. Это хороший выбор по умолчанию для небольшого положительного числа. Вы узнаете о других типах чисел в главе 3. +Метод [`parse` строк] преобразует строку в другой тип. Здесь мы используем его для преобразования строки в число. Нам нужно сообщить Rust точный числовой тип, который мы хотим получить, используя `let guess: u32`. Двоеточие ( `:` ) после `guess` говорит Rust, что мы аннотируем тип переменной. В Rust есть несколько встроенных числовых типов; `u32`, показанный здесь, представляет собой 32-битное целое число без знака. Это хороший выбор по умолчанию для небольшого положительного числа. Вы узнаете о других типах чисел в главе 3. Кроме того, аннотация u32 в этом примере программы и сравнение с secret_number означает, что Rust сделает вывод, что secret_number должен быть u32. Итак, теперь сравнение будет между двумя значениями одного типа! @@ -536,7 +536,7 @@ note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace Листинг 2-5. Игнорирование нечисловой догадки и запрос другой догадки вместо завершения программы -Мы переключаем вызов `expect` на выражение `match`, чтобы перейти от аварийного завершения при ошибке к обработке ошибки. Помните, что `parse` возвращает тип `Result`, а `Result` — это перечисление, которое имеет варианты `Ok` и `Err`. Здесь мы используем выражение `match`, как и в случае с результатом `Ordering` метода `cmp`. +Мы заменяем вызов `expect` на выражение `match`, чтобы перейти от аварийного завершения при ошибке к обработке ошибки. Помните, что `parse` возвращает тип `Result`, а `Result` — это перечисление, которое имеет варианты `Ok` и `Err`. Здесь мы используем выражение `match`, как и в случае с результатом `Ordering` метода `cmp`. Если `parse` успешно преобразует строку в число, он вернёт значение `Ok`, содержащее полученное число. Это значение `Ok` будет соответствовать шаблону первой ветки, а выражение `match` просто вернёт значение `num`, которое `parse` произвёл и поместил внутрь значения `Ok`. Это число окажется в нужной нам переменной `guess`, которую мы создали. @@ -591,3 +591,19 @@ You win! ## Заключение Этот проект — практический способ познакомить вас со многими новыми концепциями Rust: `let`, `match`, функции, использование внешних крейтов и многое другое. В следующих нескольких главах вы изучите эти концепции более подробно. Глава 3 охватывает понятия, которые есть в большинстве языков программирования, такие как переменные, типы данных и функции, и показывает, как использовать их в Rust. В главе 4 рассматривается владение — особенность, которая отличает Rust от других языков. В главе 5 обсуждаются структуры и синтаксис методов, а в главе 6 объясняется, как работают перечисления. + + +[в документации стандартной библиотеки]: ../std/prelude/index.html +["Переменные и изменчивость".]: ch03-01-variables-and-mutability.html#variables-and-mutability +[Главе 3]: ch03-04-comments.html +[`std::io::Stdin`]: ../std/io/struct.Stdin.html +[`read_line`]: ../std/io/struct.Stdin.html#method.read_line +[*перечисление*]: ch06-00-enums.html +[метод `expect`]: ../std/result/enum.Result.html#method.expect +[главе 9]: ch09-02-recoverable-errors-with-result.html +[семантическое версионирование]: http://semver.org +[Crates.io]: https://crates.io/ +[Cargo]: http://doc.crates.io +[его экосистему]: http://doc.crates.io/crates-io.html +[`match`]: ch06-02-match.html +[`parse` строк]: ../std/primitive.str.html#method.parse \ No newline at end of file