Path: utzoo!utgpu!news-server.csri.toronto.edu!cs.utexas.edu!sun-barr!apple!mips!decwrl!deccrl!bloom-beacon!eru!hagbard!sunic!mcsun!ukc!mucs!cs.man.ac.uk!mario From: mario@cs.man.ac.uk (Mario Wolczko) Newsgroups: comp.lang.smalltalk Subject: Re: Nested Control Structures Within Iterators Message-ID: <2388@m1.cs.man.ac.uk> Date: 8 Apr 91 19:55:53 GMT References: <41040@cup.portal.com> Sender: news@cs.man.ac.uk Reply-To: mario@cs.man.ac.uk (Mario Wolczko) Organization: Department of Computer Science, University of Manchester Lines: 123 In article <41040@cup.portal.com>, Will@cup.portal.com (Will E Estes) writes: > Can someone explain to me whether it is possible to place another > control structure on the same line as an iterator? Say, for instance, > that I'm iterating across a file stream and I want to continue to > do so only while some condition is true. > > input do: > [ > :char | > output nextPut: char. > "more code here" > ]. > > Now what I would like to do is qualify the iteration of do: such that > when some condition becomes true we stop iterating? One thought that > comes to mind is an equivalent to the C control structure BREAK, but > I was not able to find this. Is there someone of achieving the effect > of BREAK? And if not is there some way of further qualifying the > iterator statement? > > Thanks, > Will Estes Internet: Will@cup.portal.com > UUCP: apple!cup.portal.com!Will One of the nice things about Smalltalk is the ability to build new control structures. Appended is a goodie which, when filed in, allows you to build blocks that can be exited prematurely by sending a special "break object" the value message. So, your example would look like this: [ :break | input do: [ :char | output nextPut: char. "some test" ifTrue: [break value] ] ] valueWithExit valueWithExit evaluates a block, passing it an object that, when sent a value message, causes immediate escape from the block. Try these examples: 1 to: 10 do: [ :i | Transcript show: i printString ; cr]. [ :break | 1 to: 10 do: [ :i | Transcript show: i printString ; cr. i > 5 ifTrue: [break value]]] valueWithExit0 Mario Wolczko ______ Dept. of Computer Science Internet: mario@cs.man.ac.uk /~ ~\ The University uucp: mcsun!ukc!man.cs!mario ( __ ) Manchester M13 9PL JANET: mario@uk.ac.man.cs `-': :`-' U.K. Tel: +44-61-275 6146 (FAX: 6280) ____; ;_____________the mushroom project___________________________________ If you're using a pre-2.5 version of Smalltalk-80, you'll have to change the := to leftarrow (_). The example code (in comments) only works in Rel 4.0. I'll install this in the Manchester Archive as BlockWithExit.st. 'From Objectworks(r)\Smalltalk, Release 4 of 25 October 1990 on 8 April 1991 at 8:40:51 pm'! !BlockClosure methodsFor: 'evaluating'! valueWithExit "Self should be a block of one argument. It is evaluated, and is passed a block, which, if sent a value: message, will exit self, returning the parameter of the value: message. Used for premature returns to the caller." "| val | val := [ :exit || goSoon | goSoon := DialogView confirm: 'Exit prematurely?' . goSoon ifTrue: [exit value: 'Bye!!']. Transcript show: 'Thank you for not exiting,'. ' and have a nice day!!'] valueWithExit. Transcript show: val" ^self value: [ :exit | ^exit]! valueWithExit0 "Self should be a block of one argument. It is evaluated, and is passed a block, which, if sent a value message, will exit self. Used for premature returns to the caller." "[ :exit || goSoon | goSoon := DialogView confirm: 'Exit prematurely?' . goSoon ifTrue: [Transcript show: 'Bye!!'. exit value]. Transcript show: 'Thank you for not exiting!!'] valueWithExit0" ^self value: [^self]! withExit "Self should be a block of one argument. Returns a block which when evaluated will evaluate self, passing it an exit continuation. Used for premature returns to the caller." "| exitBlock | exitBlock := [ :exit || goSoon | goSoon := DialogView confirm: 'Exit prematurely?' . goSoon ifTrue: [exit value: 'Bye!!']. Transcript show: 'Thank you for not exiting,'. ' and have a nice day!!'] withExit. Transcript show: exitBlock value" ^[self valueWithExit]! withExit0 "Self should be a block of one argument. Returns a block which when evaluated will evaluate self, passing it an exit continuation. Used for premature returns to the caller." "| exitBlock | exitBlock := [ :exit || goSoon | goSoon := DialogView confirm: 'Exit prematurely?' . goSoon ifTrue: [Transcript show: 'Bye!!'. exit value]. Transcript show: 'Thank you for not exiting!!'] withExit0. exitBlock value" ^[self valueWithExit0]! !