Как можно решить задачу, представленную в rustlings?

Я столкнулся с проблемой в функции <b>result_with_list()</b>. Мне нужно передать ошибку из функции divide (DivisionError) обратно в вызывающую функцию. Как правильно это сделать, если я работаю с методом вектора? Вот код: <pre><code class="rust">// TODO: Calculate `a` divided by `b` if `a` is evenly divisible by `b`.
// Otherwise, return a suitable error.
fn divide(a: i64, b: i64) -&gt; Result&lt;i64, DivisionError&gt; {
    if a % b == 0 {
        return Ok(a / b);
    }
    Err(DivisionError::NotDivisible)
}

// TODO: Add the correct return type and complete the function body.
// Desired output: `Ok([1, 11, 1426, 3])`

fn result_with_list() -&gt; Result&lt;Vec&lt;i64&gt;, DivisionError&gt; {
    let numbers: [i64; 4] = [27, 297, 38502, 81];

    let division_results: Result&lt;Vec&lt;i64&gt;, DivisionError&gt; = numbers
        .into_iter()
        .map(|n| divide(n, 27))
        .collect();

    division_results
}</code></pre>
  • 11 ноября 2024 г. 13:03
Ответы на вопрос 2
Для того чтобы решить проблему с передачей ошибки из функции `divide` в функцию `result_with_list`, вам нужно правильно обработать результаты, возвращаемые методом `map`. Метод `map` не может сохранить результаты с разными типами — в вашем случае `Ok` и `Err`. Вместо этого вам нужно использовать метод `collect`, чтобы собрать результаты и обработать ошибки.

Вместо простого вызова `map`, вы можете использовать метод `filter_map`, чтобы обработать ошибки, или воспользоваться методами `try` и `collect`, которые предоставляют способ работы с `Result`.

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

```rust
#[derive(Debug)]
pub enum DivisionError {
    NotDivisible,
}

// Функция divide
fn divide(a: i64, b: i64) -> Result<i64, DivisionError> {
    if b == 0 {
        return Err(DivisionError::NotDivisible); // Не забывайте о делении на ноль!
    }
    if a % b == 0 {
        return Ok(a / b);
    }
    Err(DivisionError::NotDivisible)
}

// Функция result_with_list
fn result_with_list() -> Result<Vec<i64>, DivisionError> {
    let numbers: [i64; 4] = [27, 297, 38502, 81];

    // Используем `map` вместе с `collect`
    let division_results: Result<Vec<i64>, DivisionError> = numbers
        .iter()
        .map(|&n| divide(n, 27))  // Вызываем функцию divide для каждого элемента
        .collect();               // Смотрим на результаты

    division_results
}
```

В этом коде:
1. Мы используем `map` для обработки каждого элемента массива `numbers`. Каждое деление будет возвращать результат типа `Result<i64, DivisionError>`.
2. Метод `collect()` выполняет агрегацию результатов. Если все операции `divide` вернут `Ok`, `collect` вернет `Ok(vec)`. Если хотя бы одна операция вернет `Err`, из `collect` вернется `Err`.

Таким образом, если у вас есть хотя бы одно неудачное деление, функция `result_with_list` вернет ошибку `DivisionError`. Если все деления успешны, вы получите вектор результатов как `Ok`.
Кажется, тут не совсем корректно задача поставлена. 

Судя по desired output - нужно пропустить ошибки.

В таком случае можно вот так сделать:
let division_results: Vec<i64>= numbers
        .into_iter()
        .map(|n| divide(n, 27)
        .filter_map(Result::ok)
        .collect();

Но тогда не ясно, зачем из функции возвращать result, если и так всегда всё будет успешно.

Если оставить идею с Result в возвращаемом типе, то тогда вместо filter map за использовать просто filter и is_ok
Похожие вопросы