[PATCH] Handful of new methods

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

[PATCH] Handful of new methods

Paolo Bonzini-2
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