Nil False Exceptions Failure

[WhatWeDidStory]

Last year, we were writing a simple parser in SmalltalkLanguage. For each expression, we wanted to return the result of a parse if it succeeded, or have the parse fail.

We considered the following:

We rejected each because:

Instead, we defined a Failure class, whose instances acted like wrappers to contain the reasons for failure, and defined any object except a failure object to mean success.

 Object methods:

isSuccess ^ true.

isFailure ^ false.

ifSuccess: aBlock ^ aBlock value.

ifFailure: aBlock �do nothing�

Failure methods:

isSuccess ^ false.

isFailure ^ true.

ifSuccess: aBlock �do nothing�

ifFailure: aBlock ^ aBlock value.


Would NullObject have worked here? Or a MethodObject that had both a result query and a success query?

The "Failure" class above looks like an application of the NullObject pattern to me. Good work! -- JeffGrigg (Personally, I like exceptions. But you can do what you want.)


Why were exceptions overkill? I would have thought that exceptions would be easier than a failure wrapper, because using a wrapper forces one to write explicit exception handling by hand, rather than letting the compiler and runtime do it all for you.

Are SmalltalkLanguage exceptions very slow compared to JavaLanguage or CeePlusPlus?


Did you consider passing an error block, like:

    result := parser parse: aString ifFailed: [^nil].
This passes the buck to caller of the routine, who should have more knowledge of what they want. -- DaveHarris


Aha - yet another way to do it. Which seems to read quite similar to our way:

 (result := parser parse: aString)
     ifSuccess: [...]
     ifFailure: [...]
Which brings up the main reason I think we went with "any object = success, failure wrapper = failure", instead of exceptions. It made it more natural to write the methods, so the CodeLooksLikeTheAlgorithm?. -- StanSilver


The parsing protocol could be simplified by using separate methods for each of several queries to the parser.

  parser parse: aString.
  parser isSuccessful 
    ifTrue: [... parser result ...]
    ifFalse: [... parser errorMessage ...]
This means that the parser will have to maintain its parse state between messages, which is not uncommon for parsers. -- WardCunningham


Passing a failureBlock into the Smalltalk strikes me as the most natural way to handle this. Raising an exception is virtually identical and isn't heavyweight. The Failure object, though very elegant, strikes me as more heavyweight than either a failureBlock or exception.


See also SmalltalkAndExceptions


CategoryException CategorySmalltalk CategoryNull


EditText of this page (last edited August 28, 2007) or FindPage with title or text search