[Cuis-dev] [Ann] Refinements to Exception handling

Andres Valloud ten at smallinteger.com
Sun Oct 13 13:12:29 PDT 2019


The conversation that led to these changes went more or less like 
this... first, I noted that exception handlers that look like this:

	[:ex | ^5]

are asking for trouble, because:

a) effectively, nobody is looking at how the exception handling 
mechanism is implemented, so doing non-local return like that curtails 
the private implementation of exception handling,

b) that kind of behavior is what the messages #return, #resume, #pass, 
#outer, etc are there for,

c) when you need to debug why exceptions are behaving a certain way, the 
above exception handlers make debugging impossible because now there's 
no place to put a breakpoint (e.g. in #return, #resume, #pass, #outer, 
etc, which can be redefined for the purpose at hand in the single 
exception of interest), and finally,

d) it's possible to distort the exception handling mechanism behavior 
with non-local returns.


The vast majority of the time, I see exception handlers with non-local 
returns as very close to expressions such as these:

	#(1 2 3) asSortedCollection: [:x :y | ^x < y]

where the behavior you get is not what you expected, even though the 
code is doing exactly what was requested.  See attached for an actual 
example of what I mean.  To run the code, do these and see what happens.

	ExceptionExample new breakingStuff
	ExceptionExample new workingStuff

To me, generally speaking, these considerations push the scales against 
the apparent convenience of having exception handlers do a non-local 
return.  I do not want to have to debug that kind of convenience under 
time pressure.  I do not even want to have to change code that uses such 
convenience, because it's going to be more difficult than otherwise.


So Juan heard this and pointed out the reasoning is lovely but it's not 
that helpful because the system is doing nothing to make users aware of 
these facts.  He suggested the system should complain instead.  Thus we 
(although he says mostly I) wrote code that detects non-local return and 
complains.  I believe that code was integrated recently (this bit, he 
did on his own LOL).

Andres.

On 10/13/19 07:52, Hernan Wilkinson wrote:
> Could you provide the case were it generates problems?
> 
> On Sun, Oct 13, 2019 at 11:40 AM Hernan Wilkinson 
> <hernan.wilkinson at 10pines.com <mailto:hernan.wilkinson at 10pines.com>> wrote:
> 
>     Hi,
>       I think that forbidden a non local return in an exception handler
>     is not really the solution... Although I understand the motivation I
>     think that changing the exception handling mechanism would be better.
>       I'm going to take a look at it to see if it is possible to do it.
> 
>     Hernan.
> 
>     On Sun, Oct 13, 2019 at 10:48 AM Juan Vuletich via Cuis-dev
>     <cuis-dev at lists.cuis.st <mailto:cuis-dev at lists.cuis.st>> wrote:
> 
>         Hi Folks,
> 
>         Some time ago, Andrés (with just a tad of help from me) fixed a
>         problem
>         in Exception handling. If exception handler blocks do non-local
>         return
>         (^stuff), they will skip execution of part of the Exception
>         handling
>         system code, breaking exception return values and possibly other
>         'bad
>         things'.
> 
>         I just pushed to GitHub a few updates with this work. Now, if an
>         exception handler does a non-local return, an Error will be
>         raised. We
>         also fixed a couple of places in the image where this was being
>         done.
>         BaseImageTests pass.
> 
>         This updates have some risk of breaking your code. If you you
>         get this
>         error: 'Exception handler blocks must not do non local returns',
>         then
>         you need to adjust your code. See updates #3917 to #3922 for the
>         changes
>         done to the base image.
> 
>         Thanks,
> 
>         -- 
>         Juan Vuletich
>         www.cuis-smalltalk.org <http://www.cuis-smalltalk.org>
>         https://github.com/Cuis-Smalltalk/Cuis-Smalltalk-Dev
>         https://github.com/jvuletich
>         https://www.linkedin.com/in/juan-vuletich-75611b3
>         @JuanVuletich
> 
>         -- 
>         Cuis-dev mailing list
>         Cuis-dev at lists.cuis.st <mailto:Cuis-dev at lists.cuis.st>
>         https://lists.cuis.st/mailman/listinfo/cuis-dev
> 
> 
> 
>     -- 
>     *Hernán Wilkinson
>     Agile Software Development, Teaching & Coaching*
>     *Phone: +54-011*-4893-2057
>     *Twitter: @HernanWilkinson*
>     *site: http://www.10Pines.com <http://www.10pines.com/>*
>     Address: Alem 896, Floor 6, Buenos Aires, Argentina
> 
> 
> 
> -- 
> *Hernán Wilkinson
> Agile Software Development, Teaching & Coaching*
> *Phone: +54-011*-4893-2057
> *Twitter: @HernanWilkinson*
> *site: http://www.10Pines.com <http://www.10pines.com/>*
> Address: Alem 896, Floor 6, Buenos Aires, Argentina
-------------- next part --------------
!classDefinition: #ExceptionExample category: #'ExceptionHandling-examples'!
Object subclass: #ExceptionExample
	instanceVariableNames: ''
	classVariableNames: ''
	poolDictionaries: ''
	category: 'ExceptionHandling-examples'!

!ExceptionExample methodsFor: 'working stuff' stamp: 'sqr 10/13/2019 13:03:20'!
workingStuff

	| innerClosure |
	innerClosure := [:ex | ex return: #thwartedBadly].
	^self breakStuffWithInnerClosure: innerClosure! !


!ExceptionExample methodsFor: 'break stuff' stamp: 'sqr 10/13/2019 13:09:42'!
breakStuffWithInnerClosure: innerClosure

	| answer |
	answer := self protectedStuffToBreakWithInnerClosure: innerClosure.
	answer = #outer ifTrue: [^#workedWrong].
	answer = #thwartedBadly ifTrue: [^#thwartedProperly].
	^answer! !

!ExceptionExample methodsFor: 'break stuff' stamp: 'sqr 10/13/2019 13:06:03'!
breakingStuff

	| innerClosure |
	innerClosure := [:ex | ^#thwartedBadly].
	^self breakStuffWithInnerClosure: innerClosure! !

!ExceptionExample methodsFor: 'break stuff' stamp: 'sqr 10/13/2019 13:09:53'!
protectedStuffToBreakWithInnerClosure: innerClosure

	^[3 / 0.  #didNotFailAsItShould]
		on: ZeroDivide
		do: [:ex | innerClosure value: ex.  ex return: #outer]! !


More information about the Cuis-dev mailing list