Есть несколько способов сделать итерацию над объектами в D.
One является реализация InputRange API. Диапазоны ввода аналогичны итераторам, но имеют разные API. Внедрение интерфейса диапазона означает, что вы можете использовать все функции на вашем объекте, например map
, array
, joiner
и так далее.
D не имеет функции __iter__
для получения итератора из произвольных коллекций, поэтому вам нужно будет реализовать функцию, которая возвращает диапазон ввода.
import std.range;
auto bytes() {
return chain(mime, data, header.serialize);
}
Это будет возвращать диапазон в ubyte
ввода, состоящий из байтов в mime
, за которым следуют байт в data
, то в header.serialize
.
Вы также можете реализовать метод opApply
в своей структуре. opApply
будет работать только с foreach
, поэтому вы не можете использовать методы диапазона с ним, но он позволяет выполнять такие действия, как выполнить тело цикла в отдельных потоках.
Суть opApply
заключается в том, что D передает тело петли в opApply
как функцию; то есть foreach(x; myObj) { body }
превращается в myObj.opApply((x) { body })
.
void opApply(void delegate(ubyte[] part) loopbody) {
loopbody(mime);
loopbody(data);
loopbody(header.serialize());
}
Однако, вместо того, чтобы ни один из этих вариантов, я рекомендую вам реализовать функцию на вашем объекте, который принимает диапазонвывода и записывает в него данные.
Выходной диапазон - это объект, который принимает другие объекты и что-то делает с ними. В этом случае выходной диапазон должен принимать ubyte
s, что делает его похожим на выходной поток.
void serialize(Range)(ref Range outRange) if(isOutputRange!(Range, ubyte)) {
put(outRange, mime); -- `put` simply feeds data into the output range
put(outRange, data);
header.serialize(outRange); // No longer have to allocate/return a ubyte array
}
Пример использования, который хранит выход в Appender
, которые могут быть преобразованы в массив:
import std.array;
auto serializedDataAppender = appender!ubyte();
myMsg.serialize(serializedDataAppender);
auto serializedData = serializedDataAppender.data;
Если вы реализуете диапазон выходного сигнала на верхней части розетки, то это означает, что выходное решение не должно выделять любую память из кучи.
Отъезд Programming in D книги (в частности, Изменяется и Другие диапазоны секции) для информации о том, как реализовать свои собственные диапазоны.
Как указано в документации (http://dlang.org/spec/statement.html#ForeachStatement) Есть много способов иметь дело с заявлениями foreach. Самый простой - это, возможно, диапазон ввода, но без четкого представления о том, что вы хотите, чтобы каждая итерация возвращалась, трудно сказать, какой путь является лучшим для вашего случая. Не могли бы вы уточнить? – cym13