Hello,
Is there a way to exit loops if a condition is met? For example: 1 to: 10 do: [:x | x = 3 ifTrue: [ ... ] ] What should I write instead of three dots to exit the loop if x is equal to 3? _______________________________________________ help-smalltalk mailing list [hidden email] http://lists.gnu.org/mailman/listinfo/help-smalltalk
Canol Gökel
|
Canol Gokel wrote:
> Hello, > > Is there a way to exit loops if a condition is met? For example: > > 1 to: 10 do: [:x | > x = 3 ifTrue: [ > ... > ] > ] > > What should I write instead of three dots to exit the loop if x is equal to 3? Usual ways to do it: 1) put a return instruction in the ifTrue: block However, the interpreter will exit the current method and not execute instructions after the to:do:... 2) use some kinf of detect:ifNone: trick (1 to: 10) detect: [:x | x = 3 or: [... false.]] ifNone: []. Unusual way: 3) do it with an Exception. Create a new Exception subclass, say ExitLoop. Then write: [1 to: 10 do: [:x | x = 3 ifTrue: [ExitLoop raise] ...]] on: ExitLoop do: [:exc | exc return: nil]. Nicolas _______________________________________________ help-smalltalk mailing list [hidden email] http://lists.gnu.org/mailman/listinfo/help-smalltalk |
nice wrote:
> Canol Gokel wrote: >> Hello, >> >> Is there a way to exit loops if a condition is met? For example: >> >> 1 to: 10 do: [:x | >> x = 3 ifTrue: [ >> ... >> ] >> ] >> >> What should I write instead of three dots to exit the loop if x is >> equal to 3? > > > Usual ways to do it: > > 1) put a return instruction in the ifTrue: block > However, the interpreter will exit the current method and not execute > instructions after the to:do:... > > 2) use some kinf of detect:ifNone: trick > (1 to: 10) detect: [:x | x = 3 or: [... false.]] ifNone: []. > > > Unusual way: > > 3) do it with an Exception. > Create a new Exception subclass, say ExitLoop. > Then write: > > [1 to: 10 do: [:x | x = 3 ifTrue: [ExitLoop raise] ...]] > on: ExitLoop do: [:exc | exc return: nil]. > > > Nicolas Forgot a usual fourth way: 4) use a Stream. exit := false. stream := (1 to: 10) readStream. [ exitLoop or: [stream atEnd]] whileFalse: [| x | x := stream next. x = 3 ifTrue: [exit := true] ifFalse: [...]]. _______________________________________________ help-smalltalk mailing list [hidden email] http://lists.gnu.org/mailman/listinfo/help-smalltalk |
My preferred way is the following:
Add the following method to Object (or somewhere else): Object>>escaper: aBlock ^ aBlock value: [ ^ nil ] Then implement your loop like this: self escaper: [ :break | 1 to: 10 do: [ :x | x = 3 ifTrue: [ break value ]. ... ] ] Cheers, Lukas -- Lukas Renggli http://www.lukas-renggli.ch _______________________________________________ help-smalltalk mailing list [hidden email] http://lists.gnu.org/mailman/listinfo/help-smalltalk |
Lukas Renggli a écrit :
> My preferred way is the following: > > Add the following method to Object (or somewhere else): > > Object>>escaper: aBlock > ^ aBlock value: [ ^ nil ] > > Then implement your loop like this: > > self escaper: [ :break | > 1 to: 10 do: [ :x | > x = 3 ifTrue: [ break value ]. > ... ] ] > > Cheers, > Lukas > Very Smaltalk-ish! Even works if you want to escape nested loop: self escaper: [:breakOuter | 1 to: 10 do: [:i | self escaper: [:breakInner | 1 to: 10 do: [:j | j = 3 ifTrue: [breakInner value]. (j = 2 and: [i = 7]) ifTrue: [breakOuter value]]]]]. Nicolas _______________________________________________ help-smalltalk mailing list [hidden email] http://lists.gnu.org/mailman/listinfo/help-smalltalk |
nicolas cellier <ncellier <at> ifrance.com> writes:
> > Very Smaltalk-ish! > > Even works if you want to escape nested loop: > > self escaper: [:breakOuter | > 1 to: 10 do: [:i | > self escaper: [:breakInner | > 1 to: 10 do: [:j | > j = 3 ifTrue: [breakInner value]. > (j = 2 and: [i = 7]) ifTrue: [breakOuter value]]]]]. > > Nicolas > Thank you for your answers, I also found a solution by extending the Number class like this: Number extend [ to: stop do: aBlock butPleaseExitIf: aCondition [ <category: 'shortcuts and iterators'> | i | i := self. [(i <= stop) and: [(aCondition value: i) not]] whileTrue: [aBlock value: i. i := i + self unity] ] ] This to:do:butPleaseExitIf: selector allows you to use expressions like: 1 to: 10 do: [:x | x printNl.] butPleaseExitIf: [:x | x = 3.] _______________________________________________ help-smalltalk mailing list [hidden email] http://lists.gnu.org/mailman/listinfo/help-smalltalk
Canol Gökel
|
In reply to this post by Nicolas Cellier-3
> Forgot a usual fourth way:
you also forgot an "un" before usual, didn't you? :-) nice trick, but i've never seen it anywhere! > 4) use a Stream. > > exit := false. > stream := (1 to: 10) readStream. > [ exitLoop or: [stream atEnd]] > whileFalse: [| x | > x := stream next. > x = 3 > ifTrue: [exit := true] > ifFalse: [...]]. Paolo _______________________________________________ help-smalltalk mailing list [hidden email] http://lists.gnu.org/mailman/listinfo/help-smalltalk |
In reply to this post by ZuLuuuuuu
> Thank you for your answers, I also found a solution by extending the Number
> class like this: Nice solution (together with Lukas's). Has the advantage that *you* were able to make it up! > 1 to: 10 do: [:x | x printNl.] butPleaseExitIf: [:x | x = 3.] Or #to:do:whileFalse: Paolo _______________________________________________ help-smalltalk mailing list [hidden email] http://lists.gnu.org/mailman/listinfo/help-smalltalk |
Paolo Bonzini <bonzini <at> gnu.org> writes:
> Nice solution (together with Lukas's). Has the advantage that *you* > were able to make it up! > > Paolo > Thanks :) _______________________________________________ help-smalltalk mailing list [hidden email] http://lists.gnu.org/mailman/listinfo/help-smalltalk
Canol Gökel
|
In reply to this post by Lukas Renggli
If you don't care about performance, you can use "Continuation currentDo:" instead of "self escaper:". :-) As an additional bonus, continuations support both 0- and 1-argument value, so that you can return a value if you wish. Paolo |
Free forum by Nabble | Edit this page |