(note: this is the first of a series of essays descriging how various features of the Little Smalltalk bytecodes work). _W_h_e_r_e _I_t'_s _A_t This short note explains how the messages aaaatttt::::, aaaatttt::::ppppuuuutttt::::, and their relatives are defined and used in collections. We start by discussing the simplest form of collections, arrays and strings. The message aaaatttt:::: is not defined anywhere in class AAAArrrrrrrraaaayyyy or any of its subclasses. Instead, this message is inher- ited from class CCCCoooolllllllleeeeccccttttiiiioooonnnn, which defines it using the fol- lowing method: aaaatttt:::: index |^ self at: index ifAbsent: [ smalltalk error: 'index to at: illegal' ] The functioning of the message eeeerrrrrrrroooorrrr:::: is the topic of another essay; it is sufficient for our purposes to note only that this message prints out the error string and returns nil. By redefining aaaatttt:::: in this fashion, the subc- lasses of CCCCoooolllllllleeeeccccttttiiiioooonnnn need not be concerned about how to deal with errors in cases where no error recovery action has been specified. For an array, an index is out of bounds if it is either less than 1 or greater than the size of the array. This is tested by a method in class AAAArrrrrrrraaaayyyy: iiiinnnncccclllluuuuddddeeeessssKKKKeeeeyyyy:::: index ^ index between: 1 and: self size The message ssssiiiizzzzeeee is defined in class AAAArrrrrrrraaaayyyy in terms of the message bbbbaaaassssiiiiccccSSSSiiiizzzzeeee ssssiiiizzzzeeee ^ self basicSize The message bbbbaaaassssiiiiccccSSSSiiiizzzzeeee (as well as bbbbaaaassssiiiiccccAAAAtttt::::, discussed below) is inherited from class OOOObbbbjjjjeeeecccctttt. It can be used on any object; on non-arrays it returns the number of instance variables for the object. The messages bbbbaaaassssiiiiccccSSSSiiiizzzzeeee and bbbbaaaassssiiiiccccAAAAtttt::::ppppuuuutttt:::: can be used by system classes, for example debuggers, to access instance variables in an object without having explicit access to the instance variables. One must be careful, however, bbbbaaaassssiiiiccccAAAAtttt:::: produces a system error, and not a Smalltalk error message, if it is given an index value that is out of range. May 7, 1992 - 2 - Using iiiinnnncccclllluuuuddddeeeessssKKKKeeeeyyyy:::: for a test, a value is only accessed if the index is legal. The following method appears in class AAAArrrrrrrraaaayyyy: aaaatttt:::: index iiiiffffAAAAbbbbsssseeeennnntttt:::: exceptionBlock ^ (self includesKey: index) ifTrue: [ self basicAt: index ] ifFalse: [ exceptionBlock value ] A subclass of AAAArrrrrrrraaaayyyy is the class BBBByyyytttteeeeAAAArrrrrrrraaaayyyy. A byte array is a form of array in which the elements can only take on values from zero to 255, or to put it another way, values that can be stored in one byte. On most 16 bit machines, we can store two such bytes in the space it takes to store one object pointer. Thus, the message ssssiiiizzzzeeee is redefined in class BBBByyyytttteeeeAAAArrrrrrrraaaayyyy as follows: ssssiiiizzzzeeee |^ self basicSize * 2 Note that this implies that byte arrays always have an even number of elements. Next the message bbbbaaaassssiiiiccccAAAAtttt:::: is redefined to use a byte, instead of object, form of index. This is accomplished using a primitive method, (the message bbbbaaaassssiiiiccccAAAAtttt:::: is handled in a similar fashion in class OOOObbbbjjjjeeeecccctttt, only using a different primitive). bbbbaaaassssiiiiccccAAAAtttt:::: index |^ <26 self index> Like a byte array, a string can also store two byte values in the space it takes to store a single object pointer. Unlike a byte array, however, a string can be any length, not just an even length. Therefore the message ssssiiiizzzzeeee is redefned in class SSSSttttrrrriiiinnnngggg, a subclass of BBBByyyytttteeeeAAAArrrrrrrraaaayyyy. ssssiiiizzzzeeee |^ <14 self> Another difference between a string and a byte array is that the value returned by a string must be a character, not an integer. Therefore bbbbaaaassssiiiiccccAAAAtttt:::: must also be redefined. By using the message bbbbaaaassssiiiiccccAAAAtttt:::: defined in BBBByyyytttteeeeAAAArrrrrrrraaaayyyy, (the superclass of String, and therefore accessible via the pseudo variable ssssuuuuppppeeeerrrr) the method can obtain the integer value of the appropriate character. This value is then used to create a new instance of class CCCChhhhaaaarrrr: bbbbaaaassssiiiiccccAAAAtttt:::: index |^ Char new; value: (super basicAt: index) May 7, 1992 - 3 - A value is placed into an array using the message at:put:. As with aaaatttt::::, a value should only be placed if the index represents a legal subscript. This is checked in the following method: aaaatttt:::: index ppppuuuutttt:::: value (self includesKey: index) ifTrue: [ self basicAt: index put: value ] ifFalse: [ smalltalk error: 'illegal index to at:put: for array' ] As was the case with bbbbaaaassssiiiiccccAAAAtttt::::, one version of bbbbaaaassssiiiiccccAAAAtttt::::ppppuuuutttt::::, to be used by arrays of objects, is defined as part of class OOOObbbbjjjjeeeecccctttt. A different version is found in class BBBByyyytttteeeeAAAArrrrrrrraaaayyyy. Finally a third version, which first checks to see if the argument is a Character, is found in class SSSSttttrrrriiiinnnngggg. aaaatttt:::: index ppppuuuutttt:::: aValue (aValue isMemberOf: Char) ifTrue: [ super basicAt: index put: aValue asciiValue ] ifFalse: [ smalltalk error: 'cannot put non Char into string' ] _E_x_e_r_c_i_s_e_s 1. Describe the sequence of messages used to respond to the following: x <- #(1 2 3) at: 2 2. Describe how the execution of the above expression could be speeded up by adding new methods. Note if your methods are specific to arrays of objects, arrays of bytes, or strings. May 7, 1992