2017-05-15 8 views
1

Betrachtet wird eine Funktion query_item, die entweder ein zu bearbeitendes Objekt zurückgibt oder null, wenn nichts mehr verarbeitet werden soll.DRY bei Zuweisung eines neuen Wertes für jede Schleife

let item = query_item(); 
while(item !== null){ 
    process(item); 
    item = query_item(); 
} 

Offensichtlich ist dies eine kleine Verletzung von DRY (Do wiederholt sie nicht), meist durch query_item() als dedizierte Funktion abgeschwächt.

Ich bin mir bewusst, dass in diesem einfachen Fall die Klarheit viel wichtiger ist als die Vermeidung von Wiederholungen.

Gibt es dennoch eine Möglichkeit, eine Schleife wie diese zu schreiben, ohne die Zuweisung zu wiederholen?

Das einzige, was mir einfiel, war ein For-Loop-Ansatz, aber das hat die gleiche Wiederholung und ist - zumindest in meinen Augen - etwas schwieriger zu lesen.

for(let item = query_item(); 
    item !== null; 
    item = query_item() 
){ 
    process(item); 
}; 
+1

[Diese Antwort] (http://stackoverflow.com/questions/151850/why-have-you-use-ein-assignment-in-a-condition/151870 # 151870) könnte Ihnen helfen. –

Antwort

3

Dies ist das Standard-Szenario, in dem man einen Auftrag in der while Bedingung verwenden würde:

let item; 
while (item = query_item()) { 
    process(item); 
} 

oder möglicherweise, wenn Sie explizit sein wollen:

let item; 
while ((item = query_item()) !== null) { 
    process(item); 
} 

Sie können auch Verwenden Sie eine Schleife for mit dem gleichen Ansatz, der Ihnen auch Blockbereich für let:

bietet
for (let item; item = query_item();) { 
    process(item); 
} 
+0

Haben Sie diese Aufgabe getestet? –

+1

@MatheusValienteSouza er hat 250k rep, er braucht nicht, er * weiß * –

+0

Ah richtig, ich habe es mit der Deklaration innerhalb versucht und das hat nicht funktioniert, aber nur die Zuordnung scheint perfekt zu sein. @MatheusValienteSouza Ich sehe nicht, wie diese Aufgabe nicht funktionieren konnte. Fehle ich etwas? – iFreilicht

0

Kleiner hübscher?

let item; 
do { 
    item = query_item(); 
    if (item) process(item); 
} while (item !== null) 
+0

Das ist eine gute Verwendung für die tun, während. –

+0

Ich würde empfehlen 'sonst brechen; } while (true) 'um zu vermeiden, den Test zu wiederholen – Bergi

+1

Das macht aber den Test zweimal. Und wenn Sie nur 'if (item)' verwenden, haben Sie jetzt zwei verschiedene Bedingungen, um 'process' auszuführen und die Schleife zu unterbrechen. @Bergi hat dafür eine gute Lösung, aber es ist kaum schöner als seine Antwort. – iFreilicht

-1

der Javascript glaube ich, Sie schreiben konnte:

while(let item = query_item() && item){ 
    process(item); 
} 
+1

Nein, Sie könnten nicht. lass eine Aussage los, keinen Ausdruck ... –

0

Wenn Sie diese Zuordnung Seltsamkeit vollständig vermeiden wollen und die klarsten möglich Schleife Syntax zu erhalten, man bedenkt, könnte eine ES6 iterator mit:

function query_items() { 
    return { 
     [Symbol.iterator]() { 
      return this; 
     }, 
     next() { 
      return { 
       value: query_item(), 
       get done() { return this.value === null } 
      }; 
     } 
    }; 
} 

for (let item of query_items()) { 
    process(item); 
} 

Oder noch besser implementieren query_items als generator function sofort.

0

Eine Alternative zu assignment within the loop condition ...

let item; 
while (item = query_item()) { 
    process(item); 
} 

... ist ein generator function, die nach der Begegnung eines null Wert endet:

function* iterate(cb) { 
    let next = cb(); 
    if (next === null) return; 
    yield next, yield* iterate(cb); 
} 

for (let item of iterate(query_item)) { 
    process(item); 
}