А между тем, зацените, в nightly rust научились делать вот так:
#![feature(conservative_impl_trait)]
fn numbers() -> impl Iterator {
1 ..
}
Дословно, мы из функции возвращаем некоторый анонимный тип, всё что известно про которого - это то, что он реализует типаж Iterator, ассоциативный тип Item коего установлен в i32.
Выглядит сумбурно, но знающие люди будут со мной солидарны в том, что это единственная вещь, которой не хватало для того, чтобы итераторы было реально удобно использовать. Общеизвестно, что автовывод типов в Rust работает только внутри функции, поэтому нельзя было малой кровью собрать лесенку итераторов и вернуть результат наружу, без обязательного прописывания получившегося типа в сигнатуре. До сих пор в этих случаях людям приходилось использовать либо trait objects:
fn numbers() -> Box> {
Box::new(1 ..)
}
… что плохо, потому что здесь одна совершенно ненужная аллокация, и итерация через vtable. Либо писать вот так:
fn numbers() -> std::ops::RangeFrom {
1 ..
}
… что тоже омерзительно, по ряду причин:
- Надо знать возвращаемый тип, а он может быть сильно составным (и будет, в случае с лесенкой преобразований итератора).
- Зачастую приходится оборачивать его в newtype, чтобы не экспортировать из модуля кишки (и имплементировать соответствующий Deref).
- В некоторых случаях тип вообще невозможно прописать руками, например, когда generic биндится замыканием (а тип замыкания нельзя написать руками).
Теперь же можно совершенно спокойно возвращать анонимные типы, описав трейтами что, собственно, с этими типами можно будет делать, и компилятору этого будет достаточно, чтобы проверить, что программа написана корректно.
Помимо итераторов, данная возможность даст возможность возвращать замыкания перемещением (by move), как-то так:
#![feature(conservative_impl_trait)]
fn adder(a: i32) -> impl Fn(i32) -> i32 {
move |x| x + a
}
Это ваще космос. По факту можно будет с относительным комфортом писать в функциональном стиле на языке, в котором нет garbage collector (!!), и при этом без сегфолтов и утечек.
Да, и ещё формат ошибок в Rust теперь слизали с Elm, и они теперь выглядят максимально подробно:
Короче, я повторю свою мысль ещё раз: в 2016-м не может быть ни единой причины писать что-то на C++, когда есть Rust. Ну, может, если вы только дорабатываете какой-то уже существующий большой проект. Начинать же сейчас что-то новое на плюсах вообще безумие, никогда так не делайте :)