Диспетчеризация на основе возвращаемого типа

Перевод | Автор оригинала: Pascal Hertleif

Одна удивительная особенность вывода типов в таких языках, как Rust, - это определение функций с универсальными типами возврата. Идея состоит в том, что, указав на более позднем этапе кода, какой тип вы хотите, чтобы функция возвращала, компилятор может вернуться и заполнить пробелы.

Например, давайте посмотрим на эту функцию:

fn new<T: Default>() -> T {
  T::default()
}

Вы выбираете выход

У него нет параметров значения, но есть один параметр типа T. Этот тип T является его возвращаемым типом и также используется в теле функции. Назвать это можно так:

let x: u32 = new();

Или, если явно указать параметр типа, например:

let x = new::<i32>();

Это довольно здорово!

Более общий: сбор

Многообещающий способ сделать Rust более универсальным - использовать больше трейтов! Посмотрите, как определяется метод Iterator::collect:

fn collect<B: FromIterator<Self::Item>>(self) -> B // ...

Вы можете прочитать эту подпись типа как

Потребляйте self и возвращайте что-то типа, который реализует, может быть сделан From [an] Iterator для типа элементов, которые мы повторяем.

Как и выше, мы вызываем это, указывая, какой тип вывода нужен. [Взгляд] [разработчиков FromIterator] на некоторые из типов, для которых реализован FromIterator, довольно показывает варианты использования. Вы можете получить:

Все эти типы можно назвать «контейнерными».

Еще один в дорогу

Более общий? Больше черт.

В FromIterator спрятан еще один драгоценный камень:

impl<A, E, V> FromIterator<Result<A, E>> for Result<V, E> where
    V: FromIterator<A>, // ...

Это означает: вы можете создать Result, содержащий любой тип контейнера элементов A, собирая элементы, которые являются Результатами типа A. (Первая ошибка сделает внешний Результат ошибкой.) Вот пример, см. Документацию для другого.

let input: Vec<Result<i32,()>> = vec![Ok(1), Ok(2)];
let output: Result<Vec<i32>,()> = input.into_iter().collect();

Если вам нравится теория типов: мы создаем Result<< T , E >>, собирая Result<A, E> и указывая T.

Спасибо за чтение.