Collection.st
branchjv
changeset 17928 8e8dad2e6269
parent 17911 a99f15c5efa5
child 17938 e2aad1d7c317
--- a/Collection.st	Tue Mar 13 15:46:50 2012 +0000
+++ b/Collection.st	Wed Mar 21 17:45:38 2012 +0000
@@ -259,7 +259,6 @@
     ^ self withSize:n
 ! !
 
-
 !Collection class methodsFor:'Signal constants'!
 
 emptyCollectionSignal
@@ -314,8 +313,6 @@
     ^ self == Collection
 ! !
 
-
-
 !Collection methodsFor:'Compatibility-Dolphin'!
 
 identityIncludes:anObject
@@ -496,7 +493,6 @@
     ].
 ! !
 
-
 !Collection methodsFor:'accessing'!
 
 anElement
@@ -2003,6 +1999,19 @@
     "
 !
 
+collect:collectBlock thenDo:aBlock
+    "combination of collect followed by do.
+     Avoids the creation of intermediate garbage"
+
+    self do:[:each | aBlock value:(collectBlock value:each)]
+
+    "
+     #(1 2 3 4 5 6 7) collect:[:i | i * 2] thenDo:[:i | Transcript showCR:i ]
+    "
+
+    "Created: / 28-02-2012 / 21:05:16 / cg"
+!
+
 collect:collectBlock thenReject:rejectBlock
     "combination of collect followed by reject.
      May be redefined by some subclasses for optimal performance
@@ -2283,6 +2292,23 @@
     "Modified: / 11.2.2000 / 11:23:15 / cg"
 !
 
+do:aBlock without:anItem
+    "enumerate all elements except those equal to anItem into aBlock."
+
+    self do:[:el |
+        anItem ~= el ifTrue:[ aBlock value:el ]
+    ].
+    ^ self
+
+    "
+     #(1 2 3 4 999 5 6 7 8 9) 
+        do:[:el | Transcript showCR:el ]
+        without:5
+    "
+
+    "Created: / 28-02-2012 / 21:11:41 / cg"
+!
+
 doWithExit:aBlock
     "evaluate the argument, aBlock for each element.
      Passes an additional exit object, which can be used to leave
@@ -2295,6 +2321,7 @@
     |exit|
 
     exit := [:exitValue | ^exitValue].
+
     self do:[:el |
         aBlock value:el value:exit
     ].
@@ -2336,7 +2363,8 @@
      Transcript showCR:el.
     "
 
-    "Modified: 18.4.1996 / 14:16:59 / cg"
+    "Modified: / 18-04-1996 / 14:16:59 / cg"
+    "Modified (format): / 29-02-2012 / 11:50:02 / cg"
 !
 
 flatDo:aBlock
@@ -2369,18 +2397,20 @@
      then with the result of the first evaluation and the next element,
      and so on.  Answer the result of the final evaluation. If the receiver
      is empty, raise an error. If the receiver has a single element, answer
-     that element."
-
-    | firstValue nextValue |
-    firstValue := nextValue := Object new. "something that can't be in the receiver"
-    self do:
-        [:each |
-        nextValue := firstValue == nextValue
-                        ifTrue: [each]
-                        ifFalse: [binaryBlock value: nextValue value: each]].
-    ^nextValue == firstValue
-        ifTrue: [self emptyCollectionError]
-        ifFalse: [nextValue]
+     that element.
+     See also: inject:into:"
+
+    | first nextValue |
+
+    self emptyCheck.
+
+    first := true.
+    self do:[:each |
+        nextValue := first 
+                        ifTrue: [first := false. each]
+                        ifFalse: [binaryBlock value: nextValue value: each]
+    ].
+    ^ nextValue
 
     "
      #('if' 'it' 'is' 'to' 'be' 'it' 'is' 'up' 'to' 'me') fold: [:a :b | a, ' ', b]
@@ -2456,23 +2486,27 @@
 !
 
 map:selector
-    "for lisp fans - similar to collect"
+    "for lisp fans - similar to collect:"
 
     ^ self collect:[:eachElement | eachElement perform:selector].
 
     "
      #(1 2 3 4) map:#negated  
     "
+
+    "Modified (comment): / 29-02-2012 / 11:53:51 / cg"
 !
 
 map:selector with:arg
-    "for lisp fans - similar to collect"
+    "for lisp fans - similar to collect:"
 
     ^ self collect:[:eachElement | eachElement perform:selector with:arg].
 
     "
      #(1 2 3 4) map:#+ with:1  
     "
+
+    "Modified (comment): / 29-02-2012 / 11:53:57 / cg"
 !
 
 nonNilElementsDo:aBlock
@@ -2549,12 +2583,41 @@
     "Created: / 20-07-2011 / 00:54:41 / cg"
 !
 
+reduce:aTwoArgBlock
+    "reduce by iteratively applying aTwoArgBlock to the result from the
+     previous reduce and an element. 
+     The first evaluation is on the first two elements."
+
+    |first|
+
+    self emptyCheck.
+    first := true.
+    ^ self 
+        inject:nil 
+        into:[:accu :el |
+            first ifTrue:[
+                first := false.
+                el
+            ] ifFalse:[
+                aTwoArgBlock value:el value:accu
+            ]
+        ]
+
+    "
+     #(10 1 2 3) reduce:[:el :diff | diff - el] 
+     #(10 1 2 3) reduce:[:el :diff | diff + el] 
+    "
+
+    "Created: / 28-02-2012 / 21:16:33 / cg"
+!
+
 reduceLeft:aTwoArgBlock
     "reduce by iteratively applying aTwoArgBlock to an element and the result from the
      previous reduce. The first evaluation is on the first two elements."
 
     |first|
 
+    self emptyCheck.
     first := true.
     ^ self 
         inject:nil 
@@ -2815,6 +2878,9 @@
      (1 to:3) with:#(one two three) do:[:num :sym |
         Transcript showCR:(num->sym)
      ]
+
+     the following fail because sets do not have ordered elements
+
      (1 to:3) with:#(one two three) asSet do:[:num :sym |
         Transcript showCR:(num->sym)
      ].
@@ -2824,6 +2890,56 @@
     "
 
     "Modified: / 30-06-2011 / 17:39:47 / cg"
+    "Modified (comment): / 18-03-2012 / 15:16:50 / cg"
+!
+
+with:aCollection reverseDo:aTwoArgBlock
+    "evaluate the argument, aBlock in reverse order for successive elements from
+     each the receiver and the argument, aSequenceableCollection.
+     The second argument, aBlock must be a two-argument block.
+     This method fails if neither the receiver nor aCollection is
+     a sequenceable collection (i.e. implements numeric key access) 
+     or (new!!) if the sizes are different."
+
+    |index  "{ Class: SmallInteger }"|
+
+    aCollection size == self size ifFalse:[
+        NotEnoughElementsSignal raiseRequestErrorString:'collections must be of the same size'.
+    ].
+
+    index := self size.
+    aCollection isSequenceable ifFalse:[
+        self isSequenceable ifFalse:[
+            ^ self error:'neither collection is sequenceable'.
+        ].
+        aCollection reverseDo:[:element |
+            aTwoArgBlock value:(self at:index) value:element.
+            index := index - 1
+        ]
+    ] ifTrue:[
+        self reverseDo:[:element |
+            aTwoArgBlock value:element value:(aCollection at:index).
+            index := index - 1
+        ]
+    ]
+
+    "
+     (1 to:3) with:#(one two three) reverseDo:[:num :sym |
+        Transcript showCR:(num->sym)
+     ]
+
+     the following fail because sets do not have ordered elements
+
+     (1 to:3) with:#(one two three) asSet reverseDo:[:num :sym |
+        Transcript showCR:(num->sym)
+     ].
+     (1 to:3) asSet with:#(one two three) reverseDo:[:num :sym |
+        Transcript showCR:(num->sym)
+     ]
+    "
+
+    "Modified: / 30-06-2011 / 17:39:47 / cg"
+    "Created: / 18-03-2012 / 15:15:04 / cg"
 ! !
 
 !Collection methodsFor:'enumerating-tests'!
@@ -2947,6 +3063,32 @@
     "Modified: / 30.10.1997 / 15:52:18 / cg"
 !
 
+noModificationError
+    "a store is attempted into an immutable collection (typically: a literal).
+     For our convenience, find the method that contains me, for a nicer error message"
+
+    |creator msg context|
+
+    creator := Method allSubInstances detect:[:aMethod | (aMethod referencesGlobal:self)] ifNone:nil.
+    creator notNil ifTrue:[
+        msg := ' (' , creator whoString , ')'
+    ].
+    context := thisContext sender.
+     "
+     this error is reported on an attempt to store into an immutable collection (typically: a literal). 
+     The literal was created in creator.
+     If you press continue in the debugger, the store will be performed.
+     If you don't want this, press abort and check your code.
+     Storing into literals is VERY VERY bad coding style.
+    "
+    NoModificationError
+        raiseRequestWith:self
+        errorString:msg
+        in:context.
+
+    "Created: / 03-08-1998 / 14:47:45 / cg"
+!
+
 notEnoughElementsError
     "report an error that the operation is not allowed,  
      since not enough elements are in the collection"
@@ -2983,7 +3125,6 @@
     ^ self size max:2
 ! !
 
-
 !Collection methodsFor:'operations'!
 
 decrementAt:aKey
@@ -4184,19 +4325,15 @@
 !Collection class methodsFor:'documentation'!
 
 version
-    ^ '$Header: /cvs/stx/stx/libbasic/Collection.st,v 1.270 2011/12/21 14:59:45 cg Exp $'
+    ^ '$Header: /cvs/stx/stx/libbasic/Collection.st,v 1.274 2012/03/18 14:17:38 cg Exp $'
 !
 
 version_CVS
-    ^ 'Header: /cvs/stx/stx/libbasic/Collection.st,v 1.270 2011/12/21 14:59:45 cg Exp '
+    ^ '§Header: /cvs/stx/stx/libbasic/Collection.st,v 1.274 2012/03/18 14:17:38 cg Exp §'
 !
 
 version_SVN
-    ^ '$Id: Collection.st 10761 2012-01-19 11:46:00Z vranyj1 $'
+    ^ '$Id: Collection.st 10792 2012-03-21 17:45:38Z vranyj1 $'
 ! !
 
 Collection initialize!
-
-
-
-