In implementing a LargeArray class (for LargeWeakIdentityKeyDictionary), I've encountered two weaknesses of the current factoring of the collections classes.
- #species
When we need to grow a collection, current we use code like "array species new: size"...but, this doesn't work for my LargeArray class because I need the new instance to adopt some of the properties of the old instance (like the chunksize and the base array class).
My proposal is that we change the current factoring to instead send #speciesNew and/or #speciesNew: to the old instance. This will offer the receiver the chance to do such initialization based on its state.
- #replaceFrom:to:with:startingAt:
The primitive version of this method accesses the state of one of it's arguments (thus breaking encapsulation). When this method is called, the argument (the replacement array) has no opportunity to hook in and override the way in which its contents are being accessed. This is a problem for my LargeArray because if the LargeArray is passed as the replacement, the primtive might fail and fall through to the slower Smalltalk code that copies each element one by one. If the primitive doesn't happen to fail, it's only because the LargeArray had enough chunks, and what we get are the chunks being copies, not the actual elements.
My proposal is that we solve this issue using double dispatch. Rather than send #replaceFrom:to:with:startingAt: directly, current senders should be changed to send #startingAt:replace:from:to:. The code for this method would looke like:
SequenceableCollection startingAt: index replace: target from: start to: stop "This destructively replaces elements from start to stop in target starting at index in the receiver. Answer the receiver. No range
checks are performed."
^target replaceFrom: start to stop with: self startingAt: index
This will offer my LargeArray class the opportunity to override this method such that it can take maximum advantage of the primitive behavior to copy itself (it would override startingAt:replace:from:to: and replaceFrom:to:with:startingAt: such that it is actually re-sending these methods to its constituent chunks).
- Stephen
Actually, after a bit more thought on this, perhaps the primitive implementations of replaceFrom:to:with:startingAt: should be changed to send #startingAt:replace:from:to:, which will then send #basicReplaceFrom:to:with:startingAt:...only the basic variant will ever have the primitive implementation. That should eliminate the need to change all of the current senders of #replaceFrom:to:with:startingAt:.
- Stephen
- #replaceFrom:to:with:startingAt:
The primitive version of this method accesses the state of one of it's arguments (thus breaking encapsulation). When this method is called, the argument (the replacement array) has no opportunity to hook in and override the way in which its contents are being accessed. This is a problem for my LargeArray because if the LargeArray is passed as the replacement, the primtive might fail and fall through to the slower Smalltalk code that copies each element one by one. If the primitive doesn't happen to fail, it's only because the LargeArray had enough chunks, and what we get are the chunks being copies, not the actual elements.
My proposal is that we solve this issue using double dispatch. Rather than send #replaceFrom:to:with:startingAt: directly, current senders should be changed to send #startingAt:replace:from:to:. The code for this method would looke like:
SequenceableCollection startingAt: index replace: target from: start to: stop "This destructively replaces elements from start to stop in target starting at index in the receiver. Answer the receiver. No range
checks are performed."
^target replaceFrom: start to stop with: self startingAt: index
This will offer my LargeArray class the opportunity to override this method such that it can take maximum advantage of the primitive behavior to copy itself (it would override startingAt:replace:from:to: and replaceFrom:to:with:startingAt: such that it is actually re-sending these methods to its constituent chunks).
- Stephen
squeak-dev@lists.squeakfoundation.org