[squeak-dev] Escaping from loops in scripts

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


Hi Chris,
all I ask is a one liner method like this:

BlockClosure>>handleExit
    ^self value: [:result | ^result]

The usage I'm doing is my own business.
It is indeed very procedural, and plenty of goto like because it's just a
dumb piece of code for generating smoke tests for fdlibm.
If you want to know, I iterate other set of bits that I compose into Float
with basicAt:put:
It does not need to be object oriented, nor to be nice, just efficient.
And I don't want to be clever when I don't need to!
Lazyness rules ;)

Le dim. 9 déc. 2018 à 21:32, Chris Muller <asqueaker at gmail.com> a écrit :

> On Sun, Dec 9, 2018 at 4:37 AM Nicolas Cellier
> <nicolas.cellier.aka.nice at gmail.com> wrote:
> >
> > Hi all,
> > when writing scripts, I often need the ability to interrupt a loop.
>
> I use #detect:ifFound:ifNone: for such cases.
>
> > 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.
>
> I find nested #detect:ifFound:ifNone:'s structurally elegant enough,
> that the "detect" nomenclature doesn't bother me.
>
> > 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
>
> You want to do non-local returns to outer blocks within the same
> method?  Yikes, I love spaghetti as much as anyone, but only to eat!
> Isn't a hierarchical composition of blocks, as conveyed by modern
> tile-based coding tools like Scratch and Etoys, tremendously easier to
> follow?  Non-local returns make a method procedural by nature,
> basically like sprinkling "goto"s into your code.
>
> > 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]]
>
> OMG, LOL!!  Arrgghh!  Please, just give me the "chained ifTrue:ifFalse:"!!!
>
> The closest I've ever gotten to this is to separate error-handling
> code from processing code, to make it more readable, thus:
>
>    | error |  error := [ ^ MyError signal: 'User not found' ].
>    ^ users at: requestedId ifAbsent: error
>
> The return only even being needed because Squeak does not support
> non-resumable Exceptions.
>
> > 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.
>
> No way, I don't believe it...   :/
>
> > I don't see such support in trunk image, could we add it?
> > Do you think of a better name?
> > (not setjmp: please)
>
> If such an albatross must go in trunk, setjmp: would be good.
>
> > Unless you come with better alternatives...
>
> Whole composed expressions!
>
> > 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's "cool" for showing how terse the design of Smalltalk language and
> environment, but not something actually recommended to do I hope,
> since it simply makes the language more complex unnecessarily.
>
> My 2 cents.
>
>  - Chris
>
> > 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/165cd118/attachment.html>


More information about the Squeak-dev mailing list