[Top][All Lists]
[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
+ ]
]
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Help-smalltalk] [PATCH] Handful of new methods,
Paolo Bonzini <=