[ENH] PairedCollection class

Richard A. O'Keefe ok at atlas.otago.ac.nz
Tue Sep 4 00:59:10 UTC 2001


"Lex Spoon" <lex at cc.gatech.edu> wrote:
	By the way, there is a nice generalization of the above with:foo:
	pattern.  It looks like this:
	
		(firstArray with: secondArray) collect: [ :combo | combo first + combo
	second ]
	
	This use of #with: (which doesn't currently exist), is identical to ML
	and Haskel's "zip" function, and it allows you to use all of collect:,
	select:, reject:, do:, detect:, etc. without writing with:collect:,
	with:select:, with:reject:, etc.  In brief, the presence of a "with"
	clause can be orthogonal to which collection operation is being used.
	
Now it does exist.
Note that it can be combined, so
    ((a with: b) with: (c with: d)) collect: [:combo |
	... combo first first "a" ...
	... combo first second "b" ...
	... combo second first "c" ...
	... combo second second "d" ... ]
gives you iteration over four collections, should you want that.

'From Squeak2.8 of 13 June 2000 [latest update: #2359] on 4 September 2001 at 1:52:50 pm'!
Magnitude subclass: #Pair
	instanceVariableNames: 'first second '
	classVariableNames: ''
	poolDictionaries: ''
	category: 'Collections-Support'!

!Pair commentStamp: 'raok 9/4/2001 13:21' prior: 0!
I represent an ordered pair of objects.  Pairs exist to support iteration over two or more
collections at once and have no semantics other than aggregation.  As a rule, you
should look for a problem-domain abstraction you can use rather than reusing me.

Pair first: x second: y makes a new Pair object.
The obvious accessors are defined.
Comparison is defined as ledxicographic comparison.

My instance variables 'first' and 'second' mean what they sound like.
!
SequenceableCollection subclass: #PairedCollection
	instanceVariableNames: 'first second count size '
	classVariableNames: ''
	poolDictionaries: ''
	category: 'Collections-Sequenceable'!

!PairedCollection commentStamp: 'raok 9/4/2001 13:45' prior: 0!
I act like the sequence you would get by doing
	a with: b collect: [:x :y | Pair first: x second: y]
except that I do not allocate a new array or ordered collection, nor do I create all
the pairs straight away.  I create pairs lazily, as they are needed.  That means that
previously generated pairs can be reclaimed by the garbage collector while you are
still traversing me.  The essence of a PairedCollection is to delegate accesses to the
collections it is built from, so you are not allowed to change one.

(a with: b) collect: [:aPair| ... aPair first ... aPair second ...]
is like
a with: b collect: [:x :y| ... x ... y ...]!

!Pair methodsFor: 'comparing' stamp: 'raok 9/4/2001 13:25'!
< aPair
	first < aPair first ifTrue: [^true].
	aPair first < first ifTrue: [^false].
	^second < aPair second! !

!Pair methodsFor: 'comparing' stamp: 'raok 9/4/2001 13:24'!
= aPair
	self species = aPair species
		ifFalse: [^false]
		ifTrue: [^first = aPair first and: [second = aPair second]]! !

!Pair methodsFor: 'comparing' stamp: 'raok 9/4/2001 13:26'!
hash
	^first hash "quick and dirty"! !

!Pair methodsFor: 'accessing' stamp: 'raok 9/4/2001 13:21'!
first
	^first! !

!Pair methodsFor: 'accessing' stamp: 'raok 9/4/2001 13:22'!
first: anObject
	first _ anObject! !

!Pair methodsFor: 'accessing' stamp: 'raok 9/4/2001 13:26'!
first: x second: y
	first _ x.
	second _ y.
! !

!Pair methodsFor: 'accessing' stamp: 'raok 9/4/2001 13:22'!
second
	^second! !

!Pair methodsFor: 'accessing' stamp: 'raok 9/4/2001 13:23'!
second: anObject
	second _ anObject ! !


!Pair class methodsFor: 'instance creation' stamp: 'raok 9/4/2001 13:28'!
first: x second: y
	^self new first: x second: y! !


!SequenceableCollection methodsFor: 'converting' stamp: 'raok 9/4/2001 13:49'!
with: anotherCollection
	"answer a new PairedCollection for iteration"
	^PairedCollection first: self second: anotherCollection! !


!PairedCollection methodsFor: 'private' stamp: 'raok 9/4/2001 13:44'!
species
	"Answer the preferred class for reconstructing the receiver."
	^Array! !

!PairedCollection methodsFor: 'accessing' stamp: 'raok 9/4/2001 13:36'!
at: anIndex
	^Pair first: (first at: anIndex) second: (second at: anIndex)! !

!PairedCollection methodsFor: 'accessing' stamp: 'raok 9/4/2001 13:36'!
at: anIndex put: anObject
	self error: 'a PairdCollection cannot be changed'
! !

!PairedCollection methodsFor: 'accessing' stamp: 'raok 9/4/2001 13:49'!
first: aCollection second: anotherCollection
	aCollection size = anotherCollection size
		ifFalse: [self error: 'collection sizes must match'].
	first _ aCollection.
	second _ anotherCollection.
	size _ aCollection size.
	^self! !

!PairedCollection methodsFor: 'accessing' stamp: 'raok 9/4/2001 13:35'!
size
	^size! !


!PairedCollection class methodsFor: 'instance creation' stamp: 'raok 9/4/2001 13:46'!
first: aCollection second: anotherCollection
	^self new first: aCollection second: anotherCollection! !







More information about the Squeak-dev mailing list