А между тем, зацените, в nightly rust научились делать вот так:
#![feature(conservative_impl_trait)]
fn numbers() -> impl Iterator {
1 ..
}
Дословно, мы из функции возвращаем некоторый анонимный тип, всё что известно про которого - это то, что он реализует типаж Iterator, ассоциативный тип Item коего установлен в i32Выглядит сумбурно,
(
Read more... )
1) Надо понять, кто будет владельцем объекта. Так как в языке не используется GC, отвественным за уничтожение является владелец (owner) - согласно дизайну языка, у каждого объекта может быть только один владелец (хотя он может меняться).
Так как объект (конкретно в нашем случае это итератор или замыкание) полностью создаётся в пределах контекста функции, и этот контекст будет уничтожен после возврата значения из неё, то единственный вариант передать объект наружу - это сделать т. н. "ownership transferring": отдав владение объектом вовне, человеку, вызывающему функцию. Тогда созданный нами объект должен будет уничтожать уже он (ну, или, в свою очередь передать владение кому-то).
2) Соответственно, в сигнатуре функции должен быть явно указан тип возвращаемого значения: мы же должны получить его во владение. Для объекта, реализующего трейт итератора это сделать не так-то просто, не указав какие-то детали имплементации собственно объекта (подробнее см. http://stackoverflow.com/questions/27535289/correct-way-to-return-an-iterator ), а для замыкания в ряде случаев и вовсе невозможно, так как для них компилятор генерирует уникальный анонимный тип, который используется только для автовыведения типов.
Поэтому раньше нам, обычно, приходилось перемещать объект в heap, и прятать его за box-указатель на trait. В этом случае мы как-бы добирались до объекта через vtable (аналогично virtual-классам в плюсах). Теперь, с помощью синтаксиса "impl trait" мы можем сделать то же самое, но без лишней аллокации и виртуальных методов - типа, полноценная zero-cost абстракция :)
Reply
Вот теперь ясно. Спасибо за развернутый ответ.
Осталось в stable дождаться.
Reply
Leave a comment