@ -708,7 +708,7 @@ value is an `Err` value, this method calls the code in the *closure*, which is
@@ -708,7 +708,7 @@ value is an `Err` value, this method calls the code in the *closure*, which is
an anonymous function we define and pass as an argument to `unwrap_or_else`.
We’ll cover closures in more detail in Chapter 13. For
now, you just need to know that `unwrap_or_else` will pass the inner value of
the `Err`, which in this case is the static string `"not enough arguments"`
the `Err`, which in this case is the static string `"не хватает переменных"`
that we added in Listing 12-9, to our closure in the argument `err` that
appears between the vertical pipes. The code in the closure can then use the
`err` value when it runs.
@ -726,7 +726,7 @@ $ cargo run
@@ -726,7 +726,7 @@ $ cargo run
@ -1680,7 +1680,7 @@ expecting printed to the screen, so that means it must have ended up in the
@@ -1680,7 +1680,7 @@ expecting printed to the screen, so that means it must have ended up in the
file. This is what *output.txt* contains:
```
Problem parsing arguments: not enough arguments
Problem parsing arguments: не хватает переменных
```
Yup, our error message is being printed to standard output. It’s much more
@ -1721,7 +1721,7 @@ redirecting standard output with `>`:
@@ -1721,7 +1721,7 @@ redirecting standard output with `>`:
```
$ cargo run > output.txt
Problem parsing arguments: not enough arguments
Problem parsing arguments: не хватает переменных
```
Now we see the error onscreen and *output.txt* contains nothing, which is the
@ -1168,7 +1168,7 @@ the program. We want to ignore that and get to the next value, so first we call
@@ -1168,7 +1168,7 @@ the program. We want to ignore that and get to the next value, so first we call
`next` and do nothing with the return value. Second, we call `next` to get the
value we want to put in the `query` field of `Config`. If `next` returns a
`Some`, we use a `match` to extract the value. If it returns `None`, it means
not enough arguments were given and we return early with an `Err` value. We do
не хватает переменных were given and we return early with an `Err` value. We do
<spanclass="caption">Приложение 12-10: Выход с рукописью ошибки если создание новой <code>Config</code> терпит неудачу</span>
В этом приложении мы использовали способ, который мы ещё не рассматривали подробно: `unwrap_or_else`, который во встроенной библиотеке определён как `Result<T, E>`. Использование `unwrap_or_else` позволяет нам определить некоторые пользовательские ошибки обработки, не содержащие `panic!`. Если `Result` является значением `Ok`, поведение этого способа подобно `unwrap`: возвращает внутреннее значение из обёртки `Ok`. Однако, если значение является значением `Err`, то этот способ вызывает рукопись *замыкания*, которое является безымянной функцией, определённой заранее и передаваемую в качестве переменной в `unwrap_or_else`. Мы рассмотрим замыкания более подробно в [главе 13](ch13-00-functional-features.html). В данный мгновение, вам просто нужно знать, что `unwrap_or_else` передаст внутреннее значение `Err`, которое в этом случае является постоянной строкой `not enough arguments`, которое мы добавили в приложении 12-9, в наше замыкание как переменная `err` указанное между вертикальными линиями. Рукопись в замыкании может затем использовать значение `err` при выполнении.
В этом приложении мы использовали способ, который мы ещё не рассматривали подробно: `unwrap_or_else`, который во встроенной библиотеке определён как `Result<T, E>`. Использование `unwrap_or_else` позволяет нам определить некоторые пользовательские ошибки обработки, не содержащие `panic!`. Если `Result` является значением `Ok`, поведение этого способа подобно `unwrap`: возвращает внутреннее значение из обёртки `Ok`. Однако, если значение является значением `Err`, то этот способ вызывает рукопись *замыкания*, которое является безымянной функцией, определённой заранее и передаваемую в качестве переменной в `unwrap_or_else`. Мы рассмотрим замыкания более подробно в [главе 13](ch13-00-functional-features.html). В данный мгновение, вам просто нужно знать, что `unwrap_or_else` передаст внутреннее значение `Err`, которое в этом случае является постоянной строкой `не хватает переменных`, которое мы добавили в приложении 12-9, в наше замыкание как переменная `err` указанное между вертикальными линиями. Рукопись в замыкании может затем использовать значение `err` при выполнении.
Мы добавили новую строку `use`, чтобы подключить `process` из встроенной библиотеки в область видимости. Рукопись в замыкании, который будет запущен в случае ошибки содержит только две строчки: мы выводим значение `err` и затем вызываем `process::exit`. Функция `process::exit` немедленно остановит программу и вернёт номер, который был передан в качестве рукописи состояния выхода. Это похоже на обработку с помощью макроса `panic!`, которую мы использовали в приложении 12-8, но мы больше не получаем весь дополнительный вывод. Давай попробуем:
@ -19,7 +19,7 @@ $ cargo run > output.txt
@@ -19,7 +19,7 @@ $ cargo run > output.txt
Согласно правил написания `>` указывает оболочке записывать содержимое принятого вывода в *output.txt* вместо экрана. Мы не увидели сообщение об ошибке, которое мы ожидали увидеть на экране, так что это означает, что оно должно быть в файле. Вот что содержит *output.txt*:
```text
Problem parsing arguments: not enough arguments
Problem parsing arguments: не хватает переменных
```
Да, наше сообщение об ошибке выводится в обычный вывод. Гораздо более полезнее, чтобы подобные сообщения об ошибках выводились во встроенной поток ошибок, поэтому в файл попадают только данные из успешного запуска. Мы поменяем это.
@ -40,7 +40,7 @@ Problem parsing arguments: not enough arguments
@@ -40,7 +40,7 @@ Problem parsing arguments: not enough arguments
```console
$ cargo run > output.txt
Problem parsing arguments: not enough arguments
Problem parsing arguments: не хватает переменных
```
Теперь мы видим ошибку на экране и *output.txt* не содержит ничего, что мы ожидаем от программы приказной строки.
Обратите внимание данное объявление использует новые правила написания: `type Item` и `Self::Item`, которые определяют _сопряженный вид данных_ (associated type) с этой сущностью. Мы подробнее поговорим о сопряженных видах данных в главе 20. Сейчас вам нужно знать, что эта рукопись требует от выполнений сущности `Iterator` определить требуемый им вид данных `Item` и данный вид данных `Item` используется в способе `next`. Другими словами, вид данных `Item` будет являться видом переменной, который возвращает повторитель .
Сущность `Iterator` требует, чтобы разработчики определяли только один способ: способ `next`, который возвращает одну переменную повторителя за раз обёрнутый в исход `Some` и когда повторение завершено, возвращает `None`.
Сущность `Iterator` требует, чтобы разработчики определяли только один способ: способ `next`, который возвращает одну переменную повторителя за раз обёрнутую в исход `Some` и когда повторение более не возможно, возвращает `None`.
Мы можем вызывать способ `next` у повторителей напрямую; в приложении 13-12 показано, какие значения возвращаются при повторных вызовах `next` у повторителя, созданного из вектора.
У сущности `Iterator` есть несколько способов, выполнение которых по умолчанию предоставляется встроенной библиотекой; вы можете узнать об этих способах, просмотрев пособие API встроенной библиотеки для `Iterator`. Некоторые из этих способов вызывают `next` в своём определении, поэтому вам необходимо использовать способ `next` при выполнения сущности `Iterator`.
Способы, вызывающие `next`, называются _использующими переходниками_, поскольку их вызов использует повторитель . Примером может служить способ `sum`, который забирает во владение повторитель и перебирает переменные, многократно вызывая `next`, тем самым используя повторитель . В этапе повторения он добавляет каждая переменная к текущему итогу сложения и возвращает итоговое значение по завершении повторения. В приложении 13-13 приведена проверка, отображающая использование способа `sum`:
Способы, вызывающие `next`, называются _итоговыми переходниками_, поскольку их вызов использует повторитель . Примером может служить способ `sum`, который забирает во владение повторитель и перебирает переменные, многократно вызывая `next`, тем самым используя повторитель . В этапе повторения он добавляет каждую переменную к текущему итогу сложения и возвращает итоговое значение по завершении повторения. В приложении 13-13 приведен пример, отображающий использование способа `sum`:
_Переходники повторителей_ - это способы, определённые для сущности `Iterator`, которые не используют повторитель . Вместо этого они создают различные повторители, изменяя некоторые особенности исходного повторителя.
В приложении 13-14 показан пример вызова способа переходника повторителя `map`, который принимает замыкание и вызывает его для каждой переменной по мере повторения переменных. Способ `map` возвращает новый повторитель , который создаёт изменённые переменные. Замыкание здесь создаёт новый повторитель , в котором каждая переменная из вектора будет увеличен на 1:
В приложении 13-14 показан пример вызова способа переходника повторителя `map`, который использует замыкание и вызывает его для каждой переменной по мере повторения переменных. Способ `map` возвращает новый повторитель , который создаёт изменённые переменные. Замыкание здесь создаёт новый повторитель , в котором каждая переменная из вектора будет увеличен на 1:
<spanclass="filename">Файл: src/main.rs</span>
@ -92,11 +92,11 @@ _Переходники повторителей_ - это способы, оп
@@ -92,11 +92,11 @@ _Переходники повторителей_ - это способы, оп
Рукопись в приложении 13-14 ничего не делает; указанное нами замыкание никогда не вызывается. Предупреждение напоминает нам, почему: переходники повторителей ленивы, и здесь нам нужно потребить повторитель .
Рукопись в приложении 13-14 ничего не делает; указанное нами замыкание никогда не вызывается. Предупреждение напоминает нам, почему: переходники повторителей ленивы, и здесь нам нужно использовать повторитель .
Чтобы устранить это предупреждение и потребить повторитель , мы воспользуемся способом `collect`, который мы использовали в главе 12 с `env::args` в приложении 12-1. Этот способ использует повторитель и собирает полученные значения в собрание указанного вида данных.
Чтобы устранить это предупреждение и использовать повторитель , мы воспользуемся способом `collect`, который мы использовали в главе 12 с `env::args` в приложении 12-1. Этот способ использует повторитель и собирает полученные значения в собрание указанного вида данных.
В приложении 13-15 мы собираем в вектор итоги перебора повторителя, который возвращается в итоге вызова `map`. Этот вектор в итоге будет содержать каждая переменная исходного вектора, увеличенный на 1.
В приложении 13-15 мы собираем в вектор итоги перебора повторителя, который возвращает итог вызова `map`. Этот вектор в итоге будет содержать каждую переменную исходного вектора, увеличенную на 1.
<spanclass="filename">Файл: src/main.rs</span>
@ -106,17 +106,17 @@ _Переходники повторителей_ - это способы, оп
@@ -106,17 +106,17 @@ _Переходники повторителей_ - это способы, оп
<spanclass="caption">Приложение 13-15: Вызов способа <code>map</code> для создания нового повторителя, а затем вызов способа <code>collect</code> для использования нового повторителя и создания вектора</span>
Поскольку `map`принимает замыкание, мы можем указать любое действие, которое хотим выполнить над каждой переменной. Это отличный пример того, как замыкания позволяют задавать желаемое поведение, используя при этом особенности повторения, которые предоставляет сущность `Iterator`.
Поскольку `map`использует замыкание, мы можем указать любое действие, которое хотим выполнить над каждой переменной. Это отличный пример того, как замыкания позволяют производить необходимые нам действия, используя при этом особенности повторения, которые предоставляет сущность `Iterator`.
Вы можете выстроить цепочку из нескольких вызовов переходников повторителя для выполнения сложных действий удобном для прочтения виде. Но поскольку все повторители являются "ленивыми", для получения итогов вызовов переходников повторителя необходимо вызвать один из способов использующего переходника.
Вы можете выстроить цепочку из нескольких вызовов переходников повторителя для выполнения сложных действий удобном для прочтения виде. Но поскольку все повторители являются "ленивыми", для получения итогов вызовов переходников повторителя необходимо вызвать один из способов _итогового переходника_.
### Использование замыканий, которые получают переменные окружения
Многие переходники повторителей принимают замыкания в качестве переменных, и обычно замыкания, которые мы будем указывать в качестве переменных переходникам повторителей, это замыкания, которые определяют (получают) своё окружение.
Многие переходники повторителей используют замыкания в качестве переменных, и обычно замыкания, которые мы будем указывать в качестве переменных переходникам повторителей, это замыкания, которые определяют (получают) своё окружение.
В этом примере мы будем использовать способ `filter`, который принимает замыкание. Замыкание получает переменную из повторителя и возвращает `bool`. Если замыкание возвращает `true`, значение будет включено в повторение, создаваемую`filter`. Если замыкание возвращает `false`, значение не будет включено.
В этом примере мы будем применять способ `filter`, который использует замыкание. Замыкание получает переменную из повторителя и возвращает `bool`. Если замыкание возвращает `true`, значение будет включено в повторение, создаваемое`filter`. Если замыкание возвращает `false`, значение не будет включено.
В приложении 13-16 мы используем `filter` с замыканием, которое получает переменную `shoe_size` из своего окружения для повторения по собрания образцов стопки`Shoe`. Он будет возвращать обувь только указанного размера.
В приложении 13-16 мы используем `filter` с замыканием, которое получает переменную `shoe_size` из своего окружения с целью его повторных прогонов для добавления в вектор`Shoe`. Он будет возвращать обувь только указанного размера с указанием наименования.
<spanclass="filename">Файл: src/lib.rs</span>
@ -126,10 +126,10 @@ _Переходники повторителей_ - это способы, оп
@@ -126,10 +126,10 @@ _Переходники повторителей_ - это способы, оп
<spanclass="caption">Приложение 13-16: Использование способа <code>filter</code> с замыканием, определяющим <code>shoe_size</code></span>
Функция `shoes_in_size` принимает в качестве свойств вектор с образцами обуви и размер обуви, а возвращает вектор, содержащий только обувь указанного размера.
Функция `shoes_in_size` принимает в качестве свойств вектор с образцами обуви и размер обуви, а возвращает вектор, содержащий только обувь указанного размера с указанием наименования.
В теле `shoes_in_my_size` мы вызываем `into_iter` чтобы создать повторитель , который становится владельцем вектора. Затем мы вызываем `filter`, чтобы превратить этот повторитель в другой, который содержит только переменные, для которых замыкание возвращает `true`.
В теле `shoes_in_my_size` мы вызываем `into_iter` чтобы использовать повторитель, которому передаём право владения над вектором `Vec<Shoe>`. Затем мы вызываем способ `filter`, внутри которого используем замыкание, которое обращается к вектору `Vec<Shoe>`, производя проверку согласно условию и возвращает в случае `true` стопку `Shoe`.
Замыкание получает свойство `shoe_size` из окружения и сравнивает его с размером каждой пары обуви, оставляя только обувь указанного размера. Наконец, вызов `collect` собирает значения, возвращаемые приспособленным повторителем, в вектор, возвращаемый функцией.
Замыкание получает переменную `shoe_size` вида данных `u32` из окружения и сравнивает его с размером каждой пары обуви, оставляя только обувь указанного размера. Наконец, вызов `collect` собирает возвращенные итоги `filter` в виде стопки `Shoe`, собирая их в вектор `Vec<Shoe>`.
Проверка показывает, что когда мы вызываем `shoes_in_my_size`, мы возвращаем только туфли, размер которых совпадает с указанным нами значением.
Проверка показывает, что когда мы вызываем `shoes_in_my_size`, мы возвращаем только туфли с указанием наименования, размер которых совпадает с указанным нами значением.
Вооружившись полученными знаниями об повторителях, мы можем улучшить выполнение работы с вводом/выводом в разделе Главы 12, применяя повторители для того, чтобы сделать некоторые места в рукописи более понятными и краткими. Давайте рассмотрим, как повторители могут улучшить нашу выполнение функции `Config::build` и функции `search`.
Вооружившись полученными знаниями об повторителях, мы можем применить возможности для работы с вводом/выводом сведений, ранее рассмотрено в разделе Главы 12, применяя повторители для того, чтобы сделать упростить рукопись, сделать её более понятной и краткой. Давайте рассмотрим, как повторители могут справиться с этим при использовании функции `Config::build` и функции `search`.
<spanclass="caption">Приложение 13-17: Репродукция функции <code>Config::build</code> из приложения 12-23</span>
<spanclass="caption">Приложение 13-17: Повтор функции <code>Config::build</code> из приложения 12-23</span>
Ранее мы говорили, что не стоит беспокоиться о бесполезных вызовах `clone`, потому что мы удалим их в будущем. Ну что же, время пришло!
@ -24,7 +24,7 @@
@@ -24,7 +24,7 @@
#### Использование возвращённого повторителя напрямую
Откройте файл *src/main.rs* дела ввода-вывода, который должен выглядеть следующим образом:
Откройте файл _src/main.rs_ дела ввода-вывода, который должен выглядеть следующим образом:
<spanclass="filename">Файл: src/main.rs</span>
@ -44,7 +44,7 @@
@@ -44,7 +44,7 @@
Функция `env::args` возвращает повторитель ! Вместо того чтобы собирать значения повторителя в вектор и затем передавать срез в `Config::build`, теперь мы передаём владение повторителем, возвращённым из `env::args` в `Config::build` напрямую.
Далее нам нужно обновить определение `Config::build`. В файле *src/lib.rs* вашего дела ввода-вывода изменим ярлык `Config::build` так, чтобы она выглядела как в приложении 13-19. Это все ещё не собирается, потому что нам нужно обновить тело функции.
Далее нам нужно обновить определение `Config::build`. В файле _src/lib.rs_ вашего дела ввода-вывода изменим ярлык `Config::build` так, чтобы она выглядела как в приложении 13-19. Это все ещё не собирается, потому что нам нужно обновить тело функции.
<spanclass="filename">Файл: src/lib.rs</span>
@ -56,7 +56,7 @@
@@ -56,7 +56,7 @@
Пособие встроенной библиотеки для функции `env::args` показывает, что вид данных возвращаемого ею повторителя - `std::env::Args`, и этот вид данных использует признак `Iterator` и возвращает значения `String`.
Мы обновили ярлык функции `Config::build`, чтобы свойство `args` имело гибкий вид данных, ограниченный сущностью `impl Iterator<Item = String>` вместо `&[String]`. Такое использование правил написания `impl Trait`, которые мы обсуждали в разделе [" Сущности как свойства"]<!-- ignore --> Главы 10, означает, что `args` может быть любым видом данных, выполняющим вид данных `Iterator` и возвращающим переменные`String`.
Мы обновили ярлык функции `Config::build`, чтобы свойство `args` имело гибкий вид данных, ограниченный сущностью `impl Iterator<Item = String>` вместо `&[String]`. Такое использование правил написания `impl Trait`, которые мы обсуждали в разделе [" Сущности как свойства"]<!-- ignore --> Главы 10, означает, что `args` может быть любым видом данных, использующий сущность `Iterator` и возвращающим вид данных`String`.
Поскольку мы владеем `args` и будем изменять `args` в этапе повторения над ним, мы можем добавить ключевое слово `mut` в свод требований свойства `args`, чтобы сделать его изменяемым.
@ -72,7 +72,7 @@
@@ -72,7 +72,7 @@
<spanclass="caption">Приложение 13-20: Изменяем тело <code>Config::build</code> так, чтобы использовать способы повторителя</span>
Помните, что первое значение в возвращаемых данных `env::args` - это имя программы. Мы хотим пренебрегать его и перейти к следующему значению, поэтому сперва мы вызываем `next` и ничего не делаем с возвращаемым значением. Затем мы вызываем `next`, чтобы получить значение, которое мы хотим поместить в поле `query` в `Config`. Если `next` возвращает `Some`, мы используем `match` для извлечения значения. Если возвращается `None`, это означает, что было задано недостаточно переменных, и мы досрочно возвращаем значение `Err`. То же самое мы делаем для значения `file_path`.
Помните, что первое значение в возвращаемых данных `env::args` - это имя программы. Мы хотим пренебречь им и перейти к следующему значению, поэтому сперва мы вызываем `next` и ничего не делаем с возвращаемым значением. Затем мы вызываем `next`, чтобы получить значение, которое мы хотим поместить в поле `query` в `Config`. Если `next` возвращает `Some`, мы используем `match` для извлечения значения. Если возвращается `None`, это означает, что было задано недостаточно переменных, и мы досрочно возвращаем значение `Err`. То же самое мы делаем для значения `file_path`.
### Делаем рукопись понятнее с помощью переходников повторителей
@ -96,7 +96,7 @@
@@ -96,7 +96,7 @@
<spanclass="caption">Приложение 13-22: Использование способов переходника повторителя в выполнении функции <code>search</code></span>
Напомним, что назначение функции `search` - вернуть все строки в `contents`, которые содержат `query`. Подобно примеру `filter` в приложении 13-16, эта рукопись использует переходник`filter`, чтобы сохранить только те строки, для которых `line.contains(query)` возвращает `true`. Затем мы собираем совпадающие строки в другой вектор с помощью `collect`. Так гораздо проще! Не стесняйтесь сделать такое же изменение для использования способов повторителя в функции `search_case_insensitive`.
Напомним, что назначение функции `search` - вернуть все строки в `contents`, которые содержат `query`. Подобно примеру `filter` в приложении 13-16, эта рукопись использует способ`filter`, чтобы сохранить только те строки, для которых `line.contains(query)` возвращает `true`. Затем мы собираем совпадающие строки в другой вектор с помощью `collect`. Так гораздо проще! Не стесняйтесь сделать такое же изменение для использования способов повторителя в функции `search_case_insensitive`.