ChrisB: generatoren mit yield

Beitrag lesen

Hi,

Das yield ist hier mehr wie ein return zu verstehen, es gibt beim Aufruf von next() das Ergebnis der Expression i++ zurück.

Yield ist aus dem Englischen gar nicht so einfach zu übersetzen.
Auf nordamerikanischen „Vorfahrt gewähren“-Schildern, den auf dem Kopf stehenden roten Dreiecken wie bei uns, steht z.B. teilweise auch “Yield” drauf - und in dem Sinne, mit „warte“, würde ich es auch hier übersetzen. Warte, bis die Verkehrslage dir erlaubt, weiter zu fahren - bzw. hier, bis dir per next() gesagt wird, „weitermachen“.

Yield steigt also erst mal aus dem aktuellen Ablauf „aus“ - da hast du recht, es ist ein bisschen wie return. Nur halt mit dem Unterschied, dass man danach wieder „einsteigen“ kann, und dass die Rückgabe eines Wertes (in die Umgebung) erst durch Aufruf von next „ausgelöst“ wird.

Und die while-Schleife ist mehr eine Deklaration, die wird nicht wirklich so abgearbeitet.

Doch, abgearbeitet wird sie schon - nur nicht an einem Stück, sondern durch das yield unterbrochen.

Sie gibt nur an, dass auf dem Iterator unendlich oft .next() aufgerufen werden kann (wenn ich das richtig verstehe).

In dem gezeigten Beispiel schon. Du musst aber natürlich keine unendlich laufende Schleife nehmen, sondern kannst den Lauf auch begrenzen:

function gen() {  
   var i=0;  
   while (i<5)  
       yield i++;  
}  
var iter=gen();  
for(var x=0; x<10; ++x) {  
  alert( iter.next() );  
}

Das liefert dir alert-Meldungen mit den Werten 0 bis 4 - und danach hagelt es eine
uncaught exception: [object StopIteration]

  • weil die Schleife eben nicht mehr „fortgesetzt“ werden kann.

Man muss wohl diese Exception abfangen - eine Möglichkeit, vorher abzufragen, ob es noch ein nächstes „Element“ gibt, scheint mir nicht vorgesehen zu sein.

Welchen praktischen Nutzen die send-Methode haben soll, kann ich allerdings noch nicht ganz erkennen.

“Once a generator has been started by calling its next() method, you can use send(), passing a specific value that will be treated as the result of the last yield. The generator will then return the operand of the subsequent yield.”

function gen() {  
   var i=0;  
   while (i<10)  
       yield i++;  
}  
var iter=gen();  
for(var x=0; x<4; ++x) {  
  alert(iter.next());  
}  
alert("send: "+iter.send(1));  
for(var x=0; x<4; ++x) {  
  alert(iter.next());  
}

Hier erhalte ich jedes Mal 0, 1, 2, 3, send: 4, 5, 6, 7, 8 - egal, ob ich als Argument für send 1, 47 oder 376 verwende.

MfG ChrisB

--
RGB is totally confusing - I mean, at least #C0FFEE should be brown, right?