Exceptions/Catch an exception thrown in a nested call: Difference between revisions

Update Smalltalk example (remove box about being incomplete)
(Update Smalltalk example (remove box about being incomplete))
Line 2,675:
 
=={{header|Smalltalk}}==
{{works with|GNU Smalltalk}}
{{incomplete|Smalltalk|"Show/describe what happens when the program is run."}}
<lang smalltalk>
{{works with|Smalltalk/X}}functional code, not class based,
Exception subclass: #U0.
using blocks as functions, and anonymous exceptions (signals):
Exception subclass: #U1.
<lang Smalltalk>| u0 u1 foo bar baz|
 
Object subclass: Foo [
u0 := Signal new.
u1 := Signal new.
 
foo bazCount := [0.
2 timesRepeat:[
[ bar value ]
on: u0
do:[ 'u0 cought' printCR ]
]
].
 
foo
bar := [
[2 baz valuetimesRepeat:
[ "==>" [self bar]. "<=="
on: U0
do:
[:sig |
'Call to bar was aborted by exception U0' printNl.
sig return]]]
 
bar
baz := [
|alreadyCalled|[self baz]
 
[baz
[bazCount := bazCount + 1.
alreadyCalled isNil ifTrue:[
bazCount = 1 ifTrue: [U0 new alreadyCalled := truesignal]. u0 raise
bazCount = 2 ] ifFalseifTrue: [U1 new signal].
"Thirds time's a u1 raise charm..."]
]
]
</lang>
]
] value.
 
Running the code:
foo value</lang>
<lang Smalltalk>
"traditional" implementation, using class based exceptions,
st> Foo new foo
and method invocations:
'Call to bar was aborted by exception U0'
<lang Smalltalk>Exception
Object: Foo new "<-0x4c9a7960>" error: An exception has occurred
subclass: #U0
U1(Exception)>>signal (ExcHandling.st:254)
instanceVariableNames:''
Foo>>baz (catch_exception.st:32)
classVariableNames:''
Foo>>bar (catch_exception.st:27)
poolDictionaries:''
optimized [] in Foo>>foo (catch_exception.st:19)
category:'example'.
BlockClosure>>on:do: (BlkClosure.st:193)
Foo>>foo (catch_exception.st:20)
UndefinedObject>>executeStatements (a String:1)
nil
</lang>
 
Explanation:<br/>
Exception
Inside the foo method, inside the 2 timesRepeat: block, there is a small
subclass: #U1
block <code>[self bar]</code> which simply calls bar. This block is sent
instanceVariableNames:''
the <code>#on:do:</code> message, which will evaluate the block and catch
classVariableNames:''
any mentioned exception. First time this block is evaluated, it results in
poolDictionaries:''
a U0 exception, which we catch and handle by printing a message and
category:'example'.
returning <code>nil</code> in place of whatever the block would have
returned. The second time the block is evaluated, it results in a U1
exception, which we do ''not'' catch, so it passes to the default handler
which prints a trace and exits. The second line of the trace
<code>U1(Exception)>>signal</code> shows that this was a U1 exception.
 
Exception handling in Smalltalk is exceptional, and the exception handler
Object
(the following do: block) can do quite some cool stuff, like retrying the
subclass: #CatchMeIfYouCan
block, retrying with a different block, and even resuming evaluation at the
instanceVariableNames:'bazAlreadyCalled'
point where the exception was raised (baz in this example) having <code>U0
classVariableNames:''
new signal</code> return some value.
poolDictionaries:''
category:'example'.
 
" CatchMeIfYouCan methods "
 
foo
2 timesRepeat:[
[ self bar ]
on: U0
do:[ 'U0 cought' printCR ]
]
 
bar
self baz
 
 
baz
bazAlreadyCalled isNil ifTrue:[
bazAlreadyCalled := true.
U0 raise
] ifFalse:[
U1 raise
]
 
CatchMeIfYouCan new foo</lang>
 
=={{header|Swift}}==
Anonymous user