[Squeak-ev] [Newbie] loop-Konstrukt

Enrico Schwass deckard73 at freenet.de
Die Nov 15 22:49:36 UTC 2005


Hallo

> > Im Netz habe ich eine recht gute Zusammenfassung der Squeak-Iteratoren
> > gefunden. Mir fiel aber auf, das eine Art "loop"-"break" nicht
> > aufgeführt ist. Hier mal als Pseudo-Code fuers Lesen einer Textdatei.
> > ios := FileStream...
> > ...
> > loop: [
> >   counter := counter + 1.
> >   char := ios next.
> >   (char = nil) iftrue: break.
> >   (char = '\n') iftrue: break.
> >   (counter > 255) iftrue: break.
> > ]
> > Gibts das so nicht? Mit whileTrue: liesse sich das schöner loesen??
> > Ganz so heimisch fuehle ich mich in Smalltalk noch nicht :/
> Merkt man - du versuchst gerade, das Problem mit der "guten alten"  
> Spaghetti-Code-Methode anzugehen.

Huch...

> Ein "break" ist nichts weiter als ein GOTO *hinter* das Ende der  
> Schleife, stimmt's? 

Ja. Lies bis zum naechsten LineFeed, aber nicht mehr als 256 Zeichen
oder bis der Stream zu Ende ist. Man haette das noch mit "oder"
verknuepfen koennen, aber obs da uebersichtlicher wird ...

> Du willst also aus einem Block (das Objekt, das  
> du mit "[...]" erzeugst) hinter den Message-send von #loop: springen.  
> Dieser Block wird aber wo ganz anders abgearbeitet, nämlich tief  
> verschachtelt unten in der #loop:-Methode.

Vermutlich ist oben mein Pseudo-Code falsch verstaendlich. In Ruby sehe
das so aus

counter = 0
loop do
	counter = counter.succ
	char = STDIN.getc
	break if char == 10
	break if counter > 255
#	....
end

> *Wenn* man das unbedingt will, gibt es natürlich Möglichkeiten, um  
> über mehrere Ebenen der Aufrufkette zurückzuspringen: nicht-lokale  
> Returns, und Exceptions. Ein nicht-lokales Return ist eins, das nicht  
> frei am Ende der Methode, sondern in einem Block steht (also z.B. in  
> einem von deinen #ifTrue:-Zweigen). Exceptions sollten klar sein, die  
> sind prinzipiell wie in anderen Sprachen auch. Damit könnte man also  
> das Break nachbauen:
> 
> | n |
> n := 0.
> (1 to: 10) loop: [:i | i even ifTrue: [n := i. self loopBreak]].
> n "ergibt 2"
> 
> =========
> 
> loop: aBlock
> 	^ [self do: aBlock] on: LoopBreak do: [:ex | ex return]
> 
> loopBreak
> 	^LoopBreak signal
> 
> =========
> 
> Der vollständige Code ist im Anhang.
> 
> Aber das macht man normalerweise nicht. Höchstens um zu  
> demonstrieren, wie einfach es ist, in Smalltalk neue  
> Kontrollstrukturen einzubauen ;-)

loop ist in Ruby eine Endlosschleife. Das habe ich nicht erwaehnt. 
Alle anderen Iteratoren gibt es aber auch. Besten Dank fuer den
Beispielcode. Ist ungewohnt fuer meine Augen, das mag aber an der
Uhrzeit liegen. 

In meinem Einsteiger-Smalltalk-Buch steht nichts zu Exceptions. Oder ich
habs aufgrund des miserablen Index uebersehen.

> Was genau versuchst du denn eigentlich, da zu tun? Sieht aus wie der  
> Versuch, Low-Level-C++-Code eins-zu-eins nach Smalltalk zu portieren.  
> Es gibt sicher einen eleganteren Weg.

siehe oben. Ich lasse mir sehr gerne elegante Wege zeigen.

Aufgewachsen bin ich mit Z80-Assembler. Das haengt mir seit fast zwei
Jahrzehnten nach. Ich bin ein lausiger Programmierer :)

Bis dann
Enno