I implemented the equivalent of Python's zip and izip (the latter using
a specialized class so as to get positioning and better performance than with generators), as well as the commonly requested Number>>#to:collect: and Number>>#to:by:collect:. Would you like them in 3.0.x too? Paolo diff --git a/ChangeLog b/ChangeLog index 0a62842..52c3f19 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2008-02-01 Paolo Bonzini <[hidden email]> + + * kernel/Number.st: Add #to:collect: and #to:by:collect:. + * kernel/SeqCollect.st: Add instance side #with:... + * kernel/StreamOps.st: Add #with:... and a class implementing it. + 2008-01-27 Stephen Compall <[hidden email]> * kernel/AnsiExcept.st: Comment or private-ize uncommented methods. diff --git a/kernel/Number.st b/kernel/Number.st index b41bf7a..62516ec 100644 --- a/kernel/Number.st +++ b/kernel/Number.st @@ -919,6 +919,42 @@ implicit type coercing code for binary operations.'> i := i + self unity] ] + to: stop collect: aBlock [ + "Evaluate aBlock for each value in the interval going from the receiver + to stop by 1. The results are collected in an Array and returned." + + <category: 'shortcuts and iterators'> + | size result i j | + size := (stop - self) truncated + 1 max: 0. + result := Array new: size. + i := self. + j := 1. + [j <= size] whileTrue: + [result at: j put: (aBlock value: i). + i := i + self unity. j := j + 1]. + ^result + ] + + to: stop by: step collect: aBlock [ + "Evaluate aBlock for each value in the interval going from the receiver + to stop with the given step. The results are collected in an Array + and returned." + + <category: 'shortcuts and iterators'> + | size result i j | + size := step > 0 + ifTrue: [stop >= self ifTrue: [(stop - self) // step + 1] ifFalse: [0]] + ifFalse: [self >= stop ifTrue: [(stop - self) // step + 1] ifFalse: [0]]. + + result := Array new: size. + i := self. + j := 1. + [j <= size] whileTrue: + [result at: j put: (aBlock value: i). + i := i + step. j := j + 1]. + ^result + ] + arithmeticError: message [ <category: 'errors'> self error: message diff --git a/kernel/SeqCollect.st b/kernel/SeqCollect.st index 4aef8fa..ec2ab4b 100644 --- a/kernel/SeqCollect.st +++ b/kernel/SeqCollect.st @@ -914,6 +914,49 @@ some access and manipulation methods.'> ^newCollection ] + with: aSequenceableCollection [ + "Return an Array with the same size as the receiver and + aSequenceableCollection, each element of which is a 2-element + Arrays including one element from the receiver and one from + aSequenceableCollection." + <category: 'concatenating'> + self size = aSequenceableCollection size + ifFalse: [^SystemExceptions.InvalidSize signalOn: aSequenceableCollection]. + ^1 to: self size collect: [ :each | + { self at: each. aSequenceableCollection at: each } ] + ] + + with: seqColl1 with: seqColl2 [ + "Return an Array with the same size as the receiver and + the arguments, each element of which is a 3-element + Arrays including one element from the receiver and one from + each argument." + <category: 'concatenating'> + self size = seqColl1 size + ifFalse: [^SystemExceptions.InvalidSize signalOn: seqColl1]. + self size = seqColl2 size + ifFalse: [^SystemExceptions.InvalidSize signalOn: seqColl2]. + ^1 to: self size collect: [ :each | + { self at: each. seqColl1 at: each. seqColl2 at: each } ] + ] + + with: seqColl1 with: seqColl2 with: seqColl3 [ + "Return an Array with the same size as the receiver and + the arguments, each element of which is a 4-element + Arrays including one element from the receiver and one from + each argument." + <category: 'concatenating'> + self size = seqColl1 size + ifFalse: [^SystemExceptions.InvalidSize signalOn: seqColl1]. + self size = seqColl2 size + ifFalse: [^SystemExceptions.InvalidSize signalOn: seqColl2]. + self size = seqColl3 size + ifFalse: [^SystemExceptions.InvalidSize signalOn: seqColl3]. + ^1 to: self size collect: [ :each | + { self at: each. seqColl1 at: each. seqColl2 at: each. + seqColl3 at: each } ] + ] + matchSubCollection: aSubCollection startingAt: anIndex [ "Private - Answer whether the items from index anIndex match those in aSubCollection. The first item is ignored" diff --git a/kernel/StreamOps.st b/kernel/StreamOps.st index a5080d4..0dd11e1 100644 --- a/kernel/StreamOps.st +++ b/kernel/StreamOps.st @@ -507,6 +507,129 @@ Stream subclass: LineStream [ +Namespace current: Kernel [ + +Stream subclass: OneOfEachStream [ + | streams delta | + + <category: 'Examples-Useful tools'> + <comment: nil> + + OneOfEachStream class >> new [ + <category: 'all'> + ^#() readStream + ] + + OneOfEachStream class >> with: stream1 [ + <category: 'all'> + ^(self basicNew) + streams: {stream1} + ] + + OneOfEachStream class >> with: stream1 with: stream2 [ + <category: 'all'> + ^(self basicNew) + streams: + {stream1. + stream2} + ] + + OneOfEachStream class >> with: stream1 with: stream2 with: stream3 [ + <category: 'all'> + ^(self basicNew) + streams: + {stream1. + stream2. + stream3} + ] + + OneOfEachStream class >> with: stream1 with: stream2 with: stream3 with: stream4 [ + <category: 'all'> + ^(self basicNew) + streams: + {stream1. + stream2. + stream3. + stream4} + ] + + OneOfEachStream class >> withAll: array [ + <category: 'all'> + ^(self basicNew) + streams: array + ] + + atEnd [ + <category: 'all'> + ^streams anySatisfy: [ :each | each atEnd] + ] + + do: aBlock [ + <category: 'all'> + [ + aBlock value: + (streams collect: [:each | + each atEnd ifTrue: [ ^self ]. + each next ]) + ] repeat + ] + + next [ + <category: 'all'> + ^streams collect: [:each | + each atEnd ifTrue: [ ^self pastEnd ] ifFalse: [ each next ]] + ] + + pastEnd [ + <category: 'all'> + ^streams first pastEnd + ] + + peekFor: anObject [ + <category: 'all'> + ^self peek = anObject + ifTrue: [ streams do: [ :each | streams next ] ]; + yourself + ] + + peek [ + <category: 'all'> + ^streams collect: [:each | + each atEnd ifTrue: [ ^self pastEnd ] ifFalse: [ each peek ]] + ] + + position [ + <category: 'all'> + ^streams first position - delta + ] + + position: anInteger [ + <category: 'all'> + ^self skip: anInteger - self position + ] + + reset [ + <category: 'all'> + self position: 0 + ] + + skip: anInteger [ + <category: 'all'> + streams do: [ :each | each skip: anInteger ] + ] + + streams: arrayOfStreams [ + <category: 'initializing'> + streams := arrayOfStreams. + delta := arrayOfStreams first position. + ] +] + +] + + + + Stream extend [ , aStream [ @@ -612,5 +735,29 @@ Stream extend [ ^Kernel.CollectingStream on: self collect: aBlock ] + with: aStream [ + "Return a new Stream whose elements are 2-element + Arrays, including one element from the receiver and one from + aStream." + <category: 'concatenating'> + ^Kernel.OneOfEachStream with: self with: aStream + ] + + with: stream1 with: stream2 [ + "Return a new Stream whose elements are 3-element + Arrays, including one element from the receiver and one from + each argument." + <category: 'concatenating'> + ^Kernel.OneOfEachStream with: self with: stream1 with: stream2 + ] + + with: stream1 with: stream2 with: stream3 [ + "Return a new Stream whose elements are 3-element + Arrays, including one element from the receiver and one from + each argument." + <category: 'concatenating'> + ^Kernel.OneOfEachStream + with: self with: stream1 with: stream2 with: stream3 + ] ] _______________________________________________ help-smalltalk mailing list [hidden email] http://lists.gnu.org/mailman/listinfo/help-smalltalk |
Free forum by Nabble | Edit this page |