help-smalltalk
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Help-smalltalk] [PATCH] Handful of new methods


From: Paolo Bonzini
Subject: [Help-smalltalk] [PATCH] Handful of new methods
Date: Sat, 02 Feb 2008 10:49:29 +0100
User-agent: Thunderbird 2.0.0.9 (Macintosh/20071031)

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  <address@hidden>
+
+       * 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  <address@hidden>
 
         * 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
+    ]
 ]
 

reply via email to

[Prev in Thread] Current Thread [Next in Thread]