Ci sono diversi modi per fare iterare su oggetti in D.
Uno è quello di attuare il InputRange API. Gli intervalli di input sono simili agli iteratori, ma hanno un'API diversa. Implementare un'interfaccia di intervallo significa che è possibile utilizzare tutte le funzioni std.range
/std.algorithm
nell'oggetto, ad esempio map
, array
, joiner
e così via.
D non ha una funzione __iter__
per ottenere un iteratore da raccolte arbitrarie, quindi sarà necessario implementare una funzione che restituisce un intervallo di input.
import std.range;
auto bytes() {
return chain(mime, data, header.serialize);
}
Ciò restituirà un intervallo ubyte
ingresso, costituito dal byte mime
, seguiti dai byte data
, poi in header.serialize
.
È inoltre possibile implementare il metodo opApply
nella struct. opApply
funziona solo con foreach
, quindi non è possibile utilizzare i metodi di intervallo con esso, ma consente di eseguire operazioni come eseguire il corpo del ciclo in thread separati.
L'essenza di opApply
è che D passa il corpo del ciclo a opApply
come una funzione; ovvero, foreach(x; myObj) { body }
viene trasformato in myObj.opApply((x) { body })
.
void opApply(void delegate(ubyte[] part) loopbody) {
loopbody(mime);
loopbody(data);
loopbody(header.serialize());
}
Tuttavia, invece di una di queste opzioni, vi consiglio di implementare una funzione sul vostro oggetto che prende una gamma uscita e scrive i dati su di esso.
Un intervallo di output è un oggetto che accetta altri oggetti e fa loro qualcosa. In questo caso, l'intervallo di output deve accettare ubyte
s, rendendolo simile a un flusso di output.
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
}
Esempio di utilizzo, che memorizza l'uscita in un Appender
, che può essere convertito in un array:
import std.array;
auto serializedDataAppender = appender!ubyte();
myMsg.serialize(serializedDataAppender);
auto serializedData = serializedDataAppender.data;
Se si implementa un campo di uscita sulla parte superiore della presa, allora ciò significa che la La soluzione per l'intervallo di produzione non deve allocare alcuna memoria dall'heap.
Scopri i Programming in D libro (in particolare, le Ranges e più intervalli sezioni) per informazioni su come implementare le proprie gamme.
Come indicato nella documentazione (http://dlang.org/spec/statement.html#ForeachStatement) ci sono molti modi per trattare con dichiarazioni foreach. Il più semplice è forse il range di input, ma senza una chiara visione di ciò che vuoi che ogni iterazione restituisca è difficile dire quale sia la migliore per il tuo caso. Potresti essere più preciso? – cym13