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... Dictionary>>#error:  in Dictionary>>#at:  in Dictionary>>#at:ifAbsent: Dictionary(HashedCollection)>>#findIndex:ifAbsent: Dictionary>>#at:ifAbsent: Dictionary>>#at: UndefinedObject(Object)>>#executeStatements
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
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
Then we see a Dictionary object responding to an
(the “Dictionary>>#at:” line). This code called the object
#at:ifAbsent: message. All of a sudden,
Dictionary calls that strange method
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
at:ifAbsent: can't find the given key, and
at:ifAbsent: does the same with
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'] ]
findIndex:ifAbsent: lies in class
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...