Hello,
I'm a bit confused about exception handling, perhaps you can help please? If I have a method #foo and #foo can signal two errors FooError and UnrelatedToFooError how do I handle both errors using #on:do: without having something like... [someObject foo] on: Error do: [:error | (error class = FooError) ifTrue: ["do something specific to FooError"]. (error class = UnrelatedToFooError) ifTrue: ["do something specific to UnrelatedToFooError"]]. In Java I would do something like try { somObject.foo(); } catch (FooError e) { // do something specific to FooError } catch (UnrelatedToFooError e) { // do something specific to UnrelatedToFooError } Even if under the hood the same is happening this seems to take care of some very common code. Is there something in Smalltalk/Squeak will provide something similar? Thanks, Zulq. |
If you wish to handle FooError and UnrelatedToFooError in the same way, you can use the concatenation operator:
[ someObject foo ] on: FooError, UnrelatedToFooError do: [ : err | "handle the err" ] If, however, you wish to handle them differently you may nest them: [ [ someObject foo ] on: FooError do: [ :fooErr | "handle fooErr" ] ] on: UnrelatedToFooError do: [ :unToFooErr | "..." ] For this second case, I implemented a helper method on BlockContext that allows me to specify multiple handlers conveniently without nesting: BlockContext>>#maOn: exc1 do: block1 on: exc2 do: block2 ^ [ [ self value ] on: exc1 do: block1 ] on: exc2 do: block2 Hope this helps.. - Chris ----- Original Message ---- From: Zulq Alam <[hidden email]> To: The general-purpose Squeak developers list <[hidden email]> Sent: Monday, March 20, 2006 2:12:48 PM Subject: Exception Handling Hello, I'm a bit confused about exception handling, perhaps you can help please? If I have a method #foo and #foo can signal two errors FooError and UnrelatedToFooError how do I handle both errors using #on:do: without having something like... [someObject foo] on: Error do: [:error | (error class = FooError) ifTrue: ["do something specific to FooError"]. (error class = UnrelatedToFooError) ifTrue: ["do something specific to UnrelatedToFooError"]]. In Java I would do something like try { somObject.foo(); } catch (FooError e) { // do something specific to FooError } catch (UnrelatedToFooError e) { // do something specific to UnrelatedToFooError } Even if under the hood the same is happening this seems to take care of some very common code. Is there something in Smalltalk/Squeak will provide something similar? Thanks, Zulq. |
In reply to this post by Zulq Alam
Le Lundi 20 Mars 2006 21:12, Zulq Alam a écrit :
> Hello, > > I'm a bit confused about exception handling, perhaps you can help please? > > If I have a method #foo and #foo can signal two errors FooError and > UnrelatedToFooError how do I handle both errors using #on:do: without > having something like... > > [someObject foo] > on: Error > do: [:error | (error class = FooError) ifTrue: ["do something > specific to FooError"]. > (error class = UnrelatedToFooError) ifTrue: ["do something > specific to UnrelatedToFooError"]]. > If handler blocks are different, you might nest the two [[someObject foo] on: FooError do: [:error | "do something specific to FooError"]] on: UnrelatedToFooError do: [:error | "do something specific to UnrelatedToFooError"]. It's a little like the if/elseif chain, you have to nest them in Smalltalk. Otherwise, you could try and implement your own multiple error messages on:do:on:do: on:do:on:do:on:do: If handler blocks are the same, there is the possibility to handle a collection of errors in Visualworks, [someObject foo] on: FooError , UnrelatedToFooError do: [:error | "do something common to FooError and UnrelatedToFooError"]. but i did not see anything like this in Squeak... unless i missed something. Has anyone got elegant a solution for the second case ? Nicolas |
In reply to this post by Zulq Alam
> If handler blocks are the same, there is the possibility to handle a > collection of errors in Visualworks, > [someObject foo] > on: FooError , UnrelatedToFooError > do: [:error | "do something common to FooError and > UnrelatedToFooError"]. > > but i did not see anything like this in Squeak... unless i missed > something. Has anyone got elegant a solution for the second case ? > > Nicolas OK, Chris was faster, and also answered my question: (FooError , UnrelatedToFooError) is implemented of course in Exception class>>#, Nicolas |
In reply to this post by Nicolas Cellier-3
> From: nicolas cellier
> Sent: Monday, March 20, 2006 3:42 PM > > Le Lundi 20 Mars 2006 21:12, Zulq Alam a écrit : > > Hello, > > > > I'm a bit confused about exception handling, perhaps you can help > please? > > > > If I have a method #foo and #foo can signal two errors FooError and > > UnrelatedToFooError how do I handle both errors using #on:do: without > > having something like... > > > > [someObject foo] > > on: Error > > do: [:error | (error class = FooError) ifTrue: ["do something > > specific to FooError"]. > > (error class = UnrelatedToFooError) ifTrue: ["do something > > specific to UnrelatedToFooError"]]. > > > > If handler blocks are different, you might nest the two > > [[someObject foo] > on: FooError > do: [:error | "do something specific to FooError"]] > on: UnrelatedToFooError > do: [:error | "do something specific to UnrelatedToFooError"]. > > It's a little like the if/elseif chain, you have to nest them in > Smalltalk. > Otherwise, you could try and implement your own multiple error messages > on:do:on:do: > on:do:on:do:on:do: > > If handler blocks are the same, there is the possibility to handle a > collection of errors in Visualworks, > [someObject foo] > on: FooError , UnrelatedToFooError > do: [:error | "do something common to FooError and > UnrelatedToFooError"]. > > but i did not see anything like this in Squeak... unless i missed > something. > Has anyone got elegant a solution for the second case ? > > Nicolas > > Also you might keep in mind that subclasses of errors are handled also. If FooError were a subclass of UnrelatedToFooError, then the handler for UnrelatedToFooError would catch both. It's also a nice trick to put the handler on the error. In that case you get the following [someObject foo] on: UnrelatedToFooError "handles subclasses" do: [:error | error handleError]. Then UnrelatedToFooError >> handleError "Do something unrelated to Foo" FooError >> handleError "Do something related to Foo" You could also use a error handleErrorWith: aSomethingOrOther And then you could send it some context for handling your error. Say if the Error wrapper is on an application then handleErrorWith: anApplication would give your errorHandler the application that it could use for handling the error. Happy coding! Ron Teitelbaum |
In reply to this post by Zulq Alam
"Zulq Alam" <[hidden email]> wrote:
> Hello, > > I'm a bit confused about exception handling, perhaps you can help please? > > If I have a method #foo and #foo can signal two errors FooError and > UnrelatedToFooError how do I handle both errors using #on:do: without > having something like... > > [someObject foo] > on: Error > do: [:error | (error class = FooError) ifTrue: ["do something > specific to FooError"]. > (error class = UnrelatedToFooError) ifTrue: ["do something > specific to UnrelatedToFooError"]]. > > In Java I would do something like > > try { > somObject.foo(); > } > catch (FooError e) { > // do something specific to FooError > } > catch (UnrelatedToFooError e) { > // do something specific to UnrelatedToFooError > } > > Even if under the hood the same is happening this seems to take care of > some very common code. > > Is there something in Smalltalk/Squeak will provide something similar? > try {...} catch{...} catch {...} ... is similar to the well-known case-statement in that it enumerates a variable number of cases. This does not fit into the message syntax that does not allow for a variable number of message arguments. Given this restriction it is the correct solution to let the handler check the class of the exception. There is however one peculiarity that I should mention: The on: Error do: <handler> catches all exception that are represented as instances of Error or as instances of subclasses of Error.When you use this construct to handle only exceptions of types FooError and UnrelatedToFooError, you may have to propagate (resignal) all exceptions that you do not want to handle. You can however set up a handler that does not catch all Errors, but only the exceptions you are intersted in: /* example 1 */ [someObject foo] on: FooError, UnrelatedToFooError do: [ error | (error class = FooError) ifTrue: ["do something specific to FooError"]. (error class = UnrelatedToFooError) ifTrue: ["do something specific to UnrelatedToFooError"] ]. The message #, is defined in the class protocol of classes Exception and ExceptionSet. It is used to group exceptions into exception sets. I think you can even write: /* example 2*/ [someObject foo] on: FooError, UnrelatedToFooError do: [ error | error class caseOf: { [FooError] -> ["do something specific to FooError"]. [UnrelatedToFooError] -> ["do something specific to UnrelatedToFooError"] }. ]. Please have a look at Object >> caseOf: if you think this may be useful for you. Note that there is a difference between example 1 and this statement: [someObject foo] on: FooError, UnrelatedToFooError do: [ error | (error class isKindOf: FooError) ifTrue: ["do something specific to FooError"]. (error class isKindOf: UnrelatedToFooError) ifTrue: ["do something specific to UnrelatedToFooError"] ]. With this statement you can handle also exceptions that are represented by subclasses of either FooError or UnrelatedToFooErrror. Example 1 and example 2 are equivalent it that they both handle only exceptions of classes FooError, UnrelatedToFooError. This is not exactly what you hope to read, but it may illustrate some less frequently explained aspects of exceptions handling. Greetings, Boris |
In reply to this post by Chris Muller-2
Thank you all. All makes sense now.
Z. Chris Muller wrote: > If you wish to handle FooError and UnrelatedToFooError in the same way, you can use the concatenation operator: > > [ someObject foo ] > on: FooError, UnrelatedToFooError > do: [ : err | "handle the err" ] > > If, however, you wish to handle them differently you may nest them: > > [ [ someObject foo ] > on: FooError > do: [ :fooErr | "handle fooErr" ] ] > on: UnrelatedToFooError > do: [ :unToFooErr | "..." ] > > |
Free forum by Nabble | Edit this page |