swizard (swizard) wrote,
swizard
swizard

Category:

Вернуть итератор

А между тем, зацените, в nightly rust научились делать вот так:

#![feature(conservative_impl_trait)]

fn numbers() -> impl Iterator<Item = i32> {
    1 ..
}

Дословно, мы из функции возвращаем некоторый анонимный тип, всё что известно про которого — это то, что он реализует типаж Iterator, ассоциативный тип Item коего установлен в i32.

Выглядит сумбурно, но знающие люди будут со мной солидарны в том, что это единственная вещь, которой не хватало для того, чтобы итераторы было реально удобно использовать. Общеизвестно, что автовывод типов в Rust работает только внутри функции, поэтому нельзя было малой кровью собрать лесенку итераторов и вернуть результат наружу, без обязательного прописывания получившегося типа в сигнатуре. До сих пор в этих случаях людям приходилось использовать либо trait objects:

fn numbers() -> Box<Iterator<Item = i32>> {
    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. Ну, может, если вы только дорабатываете какой-то уже существующий большой проект. Начинать же сейчас что-то новое на плюсах вообще безумие, никогда так не делайте :)
Tags: anonymous type, closures, code, iterator, programming language, rust, trait
Subscribe
  • Post a new comment

    Error

    default userpic

    Your IP address will be recorded 

    When you submit the form an invisible reCAPTCHA check will be performed.
    You must follow the Privacy Policy and Google Terms of use.
  • 15 comments