[squeak-dev] Escaping from loops in scripts

Nicolas Cellier nicolas.cellier.aka.nice at gmail.com
Sun Dec 9 20:22:22 UTC 2018


Hi Tobias,
I don't want to pay the burden of making own class/methods, I just want to
write a dumb and dirty script.

But to answer to myself, what I asked is already in the image:

BlockClosure>>valueWithExit
      self value: [ ^nil ]

It would be more convenient with a return value, but for now it's ok.

Le dim. 9 déc. 2018 à 14:08, Tobias Pape <Das.Linux at gmx.de> a écrit :

> Hi Nicolas,
>
>
> > On 09.12.2018, at 11:37, Nicolas Cellier <
> nicolas.cellier.aka.nice at gmail.com> wrote:
> >
> > Hi all,
> > when writing scripts, I often need the ability to interrupt a loop.
> > This is the traditional break instruction of C/Python or more advanced
> exit of FORTRAN/ADA (we can tell from which nexted loop we exit).
> >
> > I could use exceptions, but then handling exit from nested loops is
> tricky (see below).
> > One possible way to do it in Smalltalk is to use blocks, and interrupt
> with non local return.
> >
>
>
> My way would be to use at most one method per loop and have an exit block
> then, like so
>
>
> A>>run: x
>   |y z |
>   y = 0.
>   z := x
>   [z < 10] whileTrue:
>      [y := self foobar: z ifExit: [ ^y].
>       z := z + 1]
>   ^ y
>
> A>> foobar: x ifExit: aBlock
>
>   | y |
>   y := x.
>   [y isOdd] whileTrue:
>     [y := y + 2.
>     " somehting something"
>     y > 3 ifTrue: aBlock]
>   ^ y
>
> Best regards
>         -Tobias
>
> > ref
> http://lists.gnu.org/archive/html/help-smalltalk/2008-06/msg00077.html
> >
> > Object>>escape: aBlock
> >     "Give the ability to exit execution of aBlock by returning control
> to sender.
> >     aBlock will take an argument, which is a door for returning control.
> >     This is useful for breaking a loop, for example:
> >      self escape: [:exit | someCollection do: [:e | e
> fullfilSomeCondition ifTrue: [exit value]. e doSometing]]"
> >     aBlock value: [^self]
> >
> > | sum |
> > sum := 0.
> > self escape: [:exitOuterLoop | someCollection do: [:e |
> >     self escape: [:exitInnerLoop | someOtherCollection do: [:e2 |
> >         e2 > e ifTrue: [exitOuterLoop value].
> >         e2 = e ifTrue: [exitInnerLoop value].
> >         sum := sum + e]]]].
> > ^sum
> >
> > We can also use the escape: inside the loop to avoid chained
> ifTrue:ifFalse:
> > but it's then convenient to let escape: return a value:
> >
> > Object>>escape: aBlock
> >     ^aBlock value: [:result | ^result]
> >
> > aCollection collect: [:e |
> >     e escape: [:return |
> >         e < 0 ifTrue: [return value: e].
> >         e > 20 ifTrue: [return value: 401 ln].
> >        (e squared + 1) ln]]
> >
> > ref
> https://stackoverflow.com/questions/7547750/smalltalk-block-can-i-explicitly-set-the-returning-value-and-stop-executing-th/11532045#11532045
> >
> > At that time, I found that amusing, now I find it useful.
> > I don't see such support in trunk image, could we add it?
> > Do you think of a better name?
> > (not setjmp: please)
> >
> > Unless you come with better alternatives... One thing that is
> questionable is that the receiver of escape: is void (escape: is a utility).
> >
> > There is
> https://stackoverflow.com/questions/52683795/gnu-smalltalk-break-from-whiletrue-loop-without-return/52702174#52702174
> > It start looking like FORTRAN/ADA exit instruction with explicit naming
> of loop but I don't like it better.
> >
> > Maybe sending the message to the block itself sounds less arbitrary.
> >
> > BlockClosure>>handleExit
> >     ^self value: [:result | ^result]
> >
> > | sum |
> > sum := 0.
> > [:exitOuterLoop | someCollection do: [:e |
> >      [:exitInnerLoop | someOtherCollection do: [:e2 |
> >         e2 > e ifTrue: [exitOuterLoop value: nil].
> >         e2 = e ifTrue: [exitInnerLoop value: nil].
> >         sum := sum + e]] handleExit ]] handleExit.
> > ^sum
> >
> > Though, I don't find such post-fixing satisfactory: exitOuterLoop and
> handleExit are too far from each other... Especially in scripts that tend
> to be longer than ordinary methods (we don't want to factor every quick and
> dirty procedure into proper classes/methods when there is no reuse
> objective or when they are too specific).
> >
>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20181209/ddf26125/attachment.html>


More information about the Squeak-dev mailing list