Next: , Previous: Simple errors, Up: Debugging

6.8.2 Nested Calls

Type the following lines:

        x := Dictionary new
        x at: 1

The error you receive will look like:

        Dictionary new: 31 "<0x33788>" error: key not found
        ...blah blah...
        [] in Dictionary>>#at:
        [] in Dictionary>>#at:ifAbsent:

The error itself is pretty clear; we asked for something within the Dictionary which wasn't there. The object which had the error is identified as Dictionary new: 31. A Dictionary's default size is 31; thus, this is the object we created with Dictionary new.

The stack backtrace shows us the inner structure of how a Dictionary responds to the #at: message. Our hand-entered command causes the usual entry for UndefinedObject(Object). Then we see a Dictionary object responding to an #at: message (the “Dictionary>>#at:” line). This code called the object with an #at:ifAbsent: message. All of a sudden, Dictionary calls that strange method #findIndex:ifAbsent:, which evaluates two blocks, and then the error happens.

To understand this better, it is necessary to know that a very common way to handle errors in Smalltalk is to hand down a block of code which will be called when an error occurs. For the Dictionary code, the at: message passes in a block of code to the at:ifAbsent: code to be called when at:ifAbsent: can't find the given key, and at:ifAbsent: does the same with findIndex:ifAbsent:. Thus, without even looking at the code for Dictionary itself, we can guess something of the code for Dictionary's implementation:

        findIndex: key ifAbsent: errCodeBlock [
            ...look for key...
            (keyNotFound) ifTrue: [ ^(errCodeBlock value) ]
        at: key [
            ^self at: key ifAbsent: [^self error: 'key not found']

Actually, findIndex:ifAbsent: lies in class HashedCollection, as that Dictionary(HashedCollection) in the backtrace says.

It would be nice if each entry on the stack backtrace included source line numbers. Unfortunately, at this point gnu Smalltalk doesn't provide this feature. Of course, you have the source code available...