#OTHER by cg
authorClaus Gittinger <cg@exept.de>
Sun, 10 Feb 2019 14:54:18 +0100
changeset 23707 d7ceab043a39
parent 23706 2ff9f4268f74
child 23708 f4a8c504ddc6
#OTHER by cg category
Collection.st
--- a/Collection.st	Sun Feb 10 14:54:15 2019 +0100
+++ b/Collection.st	Sun Feb 10 14:54:18 2019 +0100
@@ -1,5 +1,3 @@
-"{ Encoding: utf8 }"
-
 "
  COPYRIGHT (c) 1989 by Claus Gittinger
               All Rights Reserved
@@ -4747,7 +4745,7 @@
     aStream nextPut:$)
 
     "
-     #(1 2 3 'hello' $a $ü) printOn:Transcript
+     #(1 2 3 'hello' $a $ü) printOn:Transcript
      (Array new:100000) printOn:Transcript
      (Array new:100000) printOn:Stdout
      (Array new:100000) printString size
@@ -4845,10 +4843,270 @@
 
 !Collection methodsFor:'queries'!
 
+allElementsHaveTheIdenticalValue
+    "true if all elements of the receiver have the same value"
+
+    ^ self identicalValuesComputedBy:[:el | el]
+
+    "
+     #(1 2 3 5 6 7 8 9) allElementsHaveTheIdenticalValue
+     #(1 1 1 1 1 1) allElementsHaveTheIdenticalValue
+     #(1 1 1.0 1.0 1) allElementsHaveTheIdenticalValue
+     #(1 1 1.0 1.0 1) allElementsHaveTheSameValue
+    "
+!
+
+allElementsHaveTheSameValue
+    "true if all elements of the receiver have the same value"
+
+    ^ self sameValuesComputedBy:[:el | el]
+
+    "
+     #(1 2 3 5 6 7 8 9) allElementsHaveTheSameValue
+     #(1 1 1 1 1 1) allElementsHaveTheSameValue
+     #(1 1 1.0 1.0 1) allElementsHaveTheSameValue
+    "
+
+    "Created: / 21-12-2011 / 15:54:08 / cg"
+!
+
 defaultElement
     ^  nil
 !
 
+identicalValuesComputedBy:aBlock
+    "true if aBlock answers identical values for all elements of the receiver"
+
+    |first valueForFirstElement|
+
+    first := true.
+    self do:[:each |
+        first ifTrue:[
+            first := false.
+            valueForFirstElement := aBlock value:each.
+        ] ifFalse:[
+            valueForFirstElement == (aBlock value:each) ifFalse:[
+                ^ false.
+            ].
+        ].
+    ].
+    ^ true
+
+    "
+     #(1 2 3 5 6 7 8 9) sameValuesComputedBy:[:el | el even]
+     #(1 1 1 1 1 1) sameValuesComputedBy:[:el | el even]
+     #(1 1 1.0 1.0 1) sameValuesComputedBy:[:el | el even]
+     #(1 3 3 15 1) sameValuesComputedBy:[:el | el even]
+    "
+
+    "Created: / 21-12-2011 / 15:59:19 / cg"
+!
+
+includes:searchedElement
+    "return true, if an element equal to the argument, searchedElement is in the collection.
+     This compares using #= (i.e. it does not look for the object itself,
+     instead, one that compares equal).
+     See #includesIdentical: when identity is asked for.
+     This is a *very* slow fallback - many subclasses redefine this for performance."
+
+    self do:[:eachElement |
+        (searchedElement = eachElement) ifTrue:[^ true].
+    ].
+    ^ false
+
+    "Modified (format): / 30-04-2016 / 17:10:22 / cg"
+!
+
+includesAll:aCollection
+    "return true if the receiver includes all elements of
+     the argument, aCollection; false if any is missing.
+     Notice: depending on the concrete collection,
+             this method may have O² runtime behavior,
+             and may be slow for big receivers/args.
+             Think about using a Set, or Dictionary."
+
+    ^ aCollection conform:[:element | (self includes:element)]
+
+    "
+     #(1 2 3 4 5 6 7) includesAll:#(1 2 3)
+     #('hello' 'there' 'world') includesAll:#('hello' 'world')
+     #(1 2 3 4 5 6 7) includesAll:#(7 8 9)
+    "
+
+    "Modified: / 13-10-2006 / 12:54:50 / cg"
+    "Modified (comment): / 03-10-2018 / 13:14:10 / Claus Gittinger"
+!
+
+includesAllKeys:aCollectionOfKeys
+    "return true if the receiver includes all keys in aCollectionOfKeys,
+     false if any is missing."
+
+    ^ aCollectionOfKeys conform:[:element | (self includesKey:element)]
+
+    "
+     #(1 2 3 4 5 6 7) includesAll:#(1 2 3)
+     #('hello' 'there' 'world') includesAll:#('hello' 'world')
+     #(1 2 3 4 5 6 7) includesAll:#(7 8 9)
+    "
+
+    "Created: / 03-10-2018 / 13:12:16 / Claus Gittinger"
+!
+
+includesAny:searchedElementsCollection
+    "return true if the receiver includes any from the argument, aCollection.
+     Return false if it includes none.
+     Uses #= (value compare)
+     Notice: 
+        depending on the concrete collection,
+        this method may have O² runtime behavior,
+        and may be slow for big receivers/args.
+        Think about using a Set, or Dictionary.
+
+        Some speedup is also possible, by arranging highly
+        probable elements towards the beginning of aCollection, 
+        to avoid useless searches.
+
+        Also: I am not sure, if (and if so, at which breakeven),
+        it is better to reverse the loops, and walk over the receiver's
+        elements once, walking over the searched elements in the inner loop.
+        If the receiver is large, caching effects will definitely favour this,
+        as the smaller collection might fit into the cache.
+    "
+
+    |mySize searchedSize|
+
+    mySize := self size.
+    searchedSize := searchedElementsCollection size.
+    "/ avoid this only for big receivers, due to caching effects
+    (mySize < searchedSize) ifTrue:[
+        self do:[:existingElement |
+            (searchedElementsCollection includes:existingElement) ifTrue:[^ true].
+        ].
+    ] ifFalse:[
+        searchedElementsCollection do:[:searchedElement |
+            (self includes:searchedElement) ifTrue:[^ true].
+        ].
+    ].
+    ^ false
+
+    "
+     #(1 2 3 4 5 6 7) includesAny:#(1 2 3)
+     #('hello' 'there' 'world') includesAny:#('hello' 'world')
+     #(1 2 3 4 5 6 7) includesAny:#(7 8 9)
+     #(1 2 3 4 5 6 7) includesAny:#(8 9 10)
+
+     |coll|
+     coll := (1 to:10000) asOrderedCollection.
+     Time millisecondsToRun:[
+        1000000 timesRepeat:[ coll includesAny:#(500 600) ]
+     ].
+
+     |coll|
+     coll := (1 to:10000).
+     Time millisecondsToRun:[
+        1000000 timesRepeat:[ coll includesAny:#(500 600) ]
+     ].
+
+     |coll|
+     coll := (1 to:10000) asOrderedCollection.
+     Time millisecondsToRun:[
+        100000 timesRepeat:[ coll includesAny:#(-1 -10) ]
+     ].
+
+     Notice: it is redefined for string search in a subclass:
+
+     |coll|
+     coll := String new:10000 withAll:$a.
+     coll at:500 put:$b.
+     Time millisecondsToRun:[
+        100000 timesRepeat:[ coll includesAny:'bc' ]
+     ].
+
+     |coll|
+     coll := String new:10000 withAll:$a.
+     Time millisecondsToRun:[
+        100000 timesRepeat:[ coll includesAny:'bc' ]
+     ].
+
+    "
+
+    "Modified (comment): / 12-02-2017 / 11:47:42 / cg"
+    "Modified (comment): / 03-10-2018 / 13:15:39 / Claus Gittinger"
+!
+
+includesAnyIdentical:searchedElementsCollection
+    "return true, if the receiver includes any from the argument, aCollection.
+     Return false if it includes none.
+     Use identity compare for comparing.
+     Notice:
+        depending on the concrete collection,
+        this method may have O² runtime behavior for some subclasses
+        and may be slow for big receivers/args.
+        Think about using a Set or Dictionary.
+        Some speedup is also possible, by arranging highly
+        probable elements towards the beginning of aCollection, to avoid useless searches."
+
+    searchedElementsCollection do:[:element |
+        (self includesIdentical:element) ifTrue:[^ true].
+    ].
+    ^ false
+
+    "
+     #(1 2 3 4 5 6 7) includesAnyIdentical:#(1 2 3)
+     #('hello' 'there' 'world') includesAnyIdentical:#('hello' 'world')
+     #(1 2 3 4 5 6 7) includesAnyIdentical:#(7 8 9)
+     #(1 2 3 4 5 6 7) includesAnyIdentical:#(8 9 10)
+    "
+
+    "Modified (comment): / 30-04-2016 / 17:13:38 / cg"
+    "Modified (comment): / 03-10-2018 / 13:16:09 / Claus Gittinger"
+!
+
+includesAnyKey:aCollectionOfKeys
+    "return true if the receiver includes any key from aCollectionOfKeys,
+     false if none is present."
+
+    ^ aCollectionOfKeys contains:[:element | (self includesKey:element)]
+
+    "Created: / 03-10-2018 / 13:16:57 / Claus Gittinger"
+!
+
+includesIdentical:searchedElement
+    "return true, if the argument, searchedElement is in the collection.
+     This compares using #== (i.e. object identity).
+     See #includes: when equality is asked for.
+     This is a *very* slow fallback - many subclasses redefine this for performance."
+
+    self do:[:eachElement |
+        (searchedElement == eachElement) ifTrue:[^ true].
+    ].
+    ^ false
+
+    "Modified (comment): / 30-04-2016 / 17:10:34 / cg"
+!
+
+includesKey:aKey
+    ^ self subclassResponsibility
+
+    "Created: / 03-10-2018 / 13:13:31 / Claus Gittinger"
+!
+
+isEmpty
+    "return true, if the receiver is empty"
+
+    ^ self size == 0
+!
+
+isEmptyOrNil
+    "return true if I am nil or an empty collection - true here, if the receiver's size is 0,
+     (from Squeak)"
+
+    ^ self isEmpty
+
+    "Created: / 13.11.2001 / 13:17:12 / cg"
+    "Modified: / 13.11.2001 / 13:28:35 / cg"
+!
+
 isReadOnly
     "true if this is a readOnly (immutable) collection.
      Q1: should this be called isImmutable?
@@ -4873,6 +5131,82 @@
     ^ self isReadOnly not
 !
 
+notEmpty
+    "return true, if the receiver is not empty"
+
+    ^ self isEmpty not
+!
+
+notEmptyOrNil
+    "Squeak compatibility:
+     return true if I am neither nil nor an empty collection."
+
+    ^ self notEmpty
+!
+
+occurrencesOf:anElement
+    "return the number of occurrences of the argument, anElement in
+     the receiver. Uses #= (i.e. equality) compare."
+
+    |count "{ Class: SmallInteger }" |
+
+    count := 0.
+    self do:[:element |
+        (anElement = element) ifTrue:[
+            count := count + 1
+        ].
+    ].
+    ^ count
+!
+
+occurrencesOfAny:aCollectionOfElements
+    "return the number of occurrences of any in aCollectionOfElements in the receiver.
+     Uses #= (i.e. equality) compare.
+     Should be redefined in subclass(es) if ever used heavily."
+
+    |count "{ Class: SmallInteger }" |
+
+    count := 0.
+    aCollectionOfElements do:[:element |
+        count := count + (self occurrencesOf:element)
+    ].
+    ^ count
+
+    "
+     #(1 4 6 8 4 1) occurrencesOfAny:#(1 4)
+     #(1 4 6 8 4 1) occurrencesOfAny:#(2 5)
+     'hello world' occurrencesOfAny:'hel'
+    "
+!
+
+sameValuesComputedBy:aBlock
+    "true if aBlock answers equal values for all elements of the receiver"
+
+    |first valueForFirstElement|
+
+    first := true.
+    self do:[:each |
+        first ifTrue:[
+            first := false.
+            valueForFirstElement := aBlock value:each.
+        ] ifFalse:[
+            valueForFirstElement = (aBlock value:each) ifFalse:[
+                ^ false.
+            ].
+        ].
+    ].
+    ^ true
+
+    "
+     #(1 2 3 5 6 7 8 9) sameValuesComputedBy:[:el | el even]
+     #(1 1 1 1 1 1) sameValuesComputedBy:[:el | el even]
+     #(1 1 1.0 1.0 1) sameValuesComputedBy:[:el | el even]
+     #(1 3 3 15 1) sameValuesComputedBy:[:el | el even]
+    "
+
+    "Created: / 21-12-2011 / 15:59:19 / cg"
+!
+
 size
     "return the number of elements in the receiver.
      This is usually redefined in subclasses for more performance."
@@ -6022,33 +6356,6 @@
 
 !Collection methodsFor:'testing'!
 
-allElementsHaveTheIdenticalValue
-    "true if all elements of the receiver have the same value"
-
-    ^ self identicalValuesComputedBy:[:el | el]
-
-    "
-     #(1 2 3 5 6 7 8 9) allElementsHaveTheIdenticalValue
-     #(1 1 1 1 1 1) allElementsHaveTheIdenticalValue
-     #(1 1 1.0 1.0 1) allElementsHaveTheIdenticalValue
-     #(1 1 1.0 1.0 1) allElementsHaveTheSameValue
-    "
-!
-
-allElementsHaveTheSameValue
-    "true if all elements of the receiver have the same value"
-
-    ^ self sameValuesComputedBy:[:el | el]
-
-    "
-     #(1 2 3 5 6 7 8 9) allElementsHaveTheSameValue
-     #(1 1 1 1 1 1) allElementsHaveTheSameValue
-     #(1 1 1.0 1.0 1) allElementsHaveTheSameValue
-    "
-
-    "Created: / 21-12-2011 / 15:54:08 / cg"
-!
-
 capacity
     "return the number of elements, that the receiver is prepared to take. 
      For most collections, this is the actual size. 
@@ -6060,223 +6367,6 @@
     "Modified (comment): / 17-03-2017 / 11:50:34 / stefan"
 !
 
-identicalValuesComputedBy:aBlock
-    "true if aBlock answers identical values for all elements of the receiver"
-
-    |first valueForFirstElement|
-
-    first := true.
-    self do:[:each |
-        first ifTrue:[
-            first := false.
-            valueForFirstElement := aBlock value:each.
-        ] ifFalse:[
-            valueForFirstElement == (aBlock value:each) ifFalse:[
-                ^ false.
-            ].
-        ].
-    ].
-    ^ true
-
-    "
-     #(1 2 3 5 6 7 8 9) sameValuesComputedBy:[:el | el even]
-     #(1 1 1 1 1 1) sameValuesComputedBy:[:el | el even]
-     #(1 1 1.0 1.0 1) sameValuesComputedBy:[:el | el even]
-     #(1 3 3 15 1) sameValuesComputedBy:[:el | el even]
-    "
-
-    "Created: / 21-12-2011 / 15:59:19 / cg"
-!
-
-includes:searchedElement
-    "return true, if an element equal to the argument, searchedElement is in the collection.
-     This compares using #= (i.e. it does not look for the object itself,
-     instead, one that compares equal).
-     See #includesIdentical: when identity is asked for.
-     This is a *very* slow fallback - many subclasses redefine this for performance."
-
-    self do:[:eachElement |
-        (searchedElement = eachElement) ifTrue:[^ true].
-    ].
-    ^ false
-
-    "Modified (format): / 30-04-2016 / 17:10:22 / cg"
-!
-
-includesAll:aCollection
-    "return true if the receiver includes all elements of
-     the argument, aCollection; false if any is missing.
-     Notice: depending on the concrete collection,
-             this method may have O² runtime behavior,
-             and may be slow for big receivers/args.
-             Think about using a Set, or Dictionary."
-
-    ^ aCollection conform:[:element | (self includes:element)]
-
-    "
-     #(1 2 3 4 5 6 7) includesAll:#(1 2 3)
-     #('hello' 'there' 'world') includesAll:#('hello' 'world')
-     #(1 2 3 4 5 6 7) includesAll:#(7 8 9)
-    "
-
-    "Modified: / 13-10-2006 / 12:54:50 / cg"
-    "Modified (comment): / 03-10-2018 / 13:14:10 / Claus Gittinger"
-!
-
-includesAllKeys:aCollectionOfKeys
-    "return true if the receiver includes all keys in aCollectionOfKeys,
-     false if any is missing."
-
-    ^ aCollectionOfKeys conform:[:element | (self includesKey:element)]
-
-    "
-     #(1 2 3 4 5 6 7) includesAll:#(1 2 3)
-     #('hello' 'there' 'world') includesAll:#('hello' 'world')
-     #(1 2 3 4 5 6 7) includesAll:#(7 8 9)
-    "
-
-    "Created: / 03-10-2018 / 13:12:16 / Claus Gittinger"
-!
-
-includesAny:searchedElementsCollection
-    "return true if the receiver includes any from the argument, aCollection.
-     Return false if it includes none.
-     Uses #= (value compare)
-     Notice: 
-        depending on the concrete collection,
-        this method may have O² runtime behavior,
-        and may be slow for big receivers/args.
-        Think about using a Set, or Dictionary.
-
-        Some speedup is also possible, by arranging highly
-        probable elements towards the beginning of aCollection, 
-        to avoid useless searches.
-
-        Also: I am not sure, if (and if so, at which breakeven),
-        it is better to reverse the loops, and walk over the receiver's
-        elements once, walking over the searched elements in the inner loop.
-        If the receiver is large, caching effects will definitely favour this,
-        as the smaller collection might fit into the cache.
-    "
-
-    |mySize searchedSize|
-
-    mySize := self size.
-    searchedSize := searchedElementsCollection size.
-    "/ avoid this only for big receivers, due to caching effects
-    (mySize < searchedSize) ifTrue:[
-        self do:[:existingElement |
-            (searchedElementsCollection includes:existingElement) ifTrue:[^ true].
-        ].
-    ] ifFalse:[
-        searchedElementsCollection do:[:searchedElement |
-            (self includes:searchedElement) ifTrue:[^ true].
-        ].
-    ].
-    ^ false
-
-    "
-     #(1 2 3 4 5 6 7) includesAny:#(1 2 3)
-     #('hello' 'there' 'world') includesAny:#('hello' 'world')
-     #(1 2 3 4 5 6 7) includesAny:#(7 8 9)
-     #(1 2 3 4 5 6 7) includesAny:#(8 9 10)
-
-     |coll|
-     coll := (1 to:10000) asOrderedCollection.
-     Time millisecondsToRun:[
-        1000000 timesRepeat:[ coll includesAny:#(500 600) ]
-     ].
-
-     |coll|
-     coll := (1 to:10000).
-     Time millisecondsToRun:[
-        1000000 timesRepeat:[ coll includesAny:#(500 600) ]
-     ].
-
-     |coll|
-     coll := (1 to:10000) asOrderedCollection.
-     Time millisecondsToRun:[
-        100000 timesRepeat:[ coll includesAny:#(-1 -10) ]
-     ].
-
-     Notice: it is redefined for string search in a subclass:
-
-     |coll|
-     coll := String new:10000 withAll:$a.
-     coll at:500 put:$b.
-     Time millisecondsToRun:[
-        100000 timesRepeat:[ coll includesAny:'bc' ]
-     ].
-
-     |coll|
-     coll := String new:10000 withAll:$a.
-     Time millisecondsToRun:[
-        100000 timesRepeat:[ coll includesAny:'bc' ]
-     ].
-
-    "
-
-    "Modified (comment): / 12-02-2017 / 11:47:42 / cg"
-    "Modified (comment): / 03-10-2018 / 13:15:39 / Claus Gittinger"
-!
-
-includesAnyIdentical:searchedElementsCollection
-    "return true, if the receiver includes any from the argument, aCollection.
-     Return false if it includes none.
-     Use identity compare for comparing.
-     Notice:
-        depending on the concrete collection,
-        this method may have O² runtime behavior for some subclasses
-        and may be slow for big receivers/args.
-        Think about using a Set or Dictionary.
-        Some speedup is also possible, by arranging highly
-        probable elements towards the beginning of aCollection, to avoid useless searches."
-
-    searchedElementsCollection do:[:element |
-        (self includesIdentical:element) ifTrue:[^ true].
-    ].
-    ^ false
-
-    "
-     #(1 2 3 4 5 6 7) includesAnyIdentical:#(1 2 3)
-     #('hello' 'there' 'world') includesAnyIdentical:#('hello' 'world')
-     #(1 2 3 4 5 6 7) includesAnyIdentical:#(7 8 9)
-     #(1 2 3 4 5 6 7) includesAnyIdentical:#(8 9 10)
-    "
-
-    "Modified (comment): / 30-04-2016 / 17:13:38 / cg"
-    "Modified (comment): / 03-10-2018 / 13:16:09 / Claus Gittinger"
-!
-
-includesAnyKey:aCollectionOfKeys
-    "return true if the receiver includes any key from aCollectionOfKeys,
-     false if none is present."
-
-    ^ aCollectionOfKeys contains:[:element | (self includesKey:element)]
-
-    "Created: / 03-10-2018 / 13:16:57 / Claus Gittinger"
-!
-
-includesIdentical:searchedElement
-    "return true, if the argument, searchedElement is in the collection.
-     This compares using #== (i.e. object identity).
-     See #includes: when equality is asked for.
-     This is a *very* slow fallback - many subclasses redefine this for performance."
-
-    self do:[:eachElement |
-        (searchedElement == eachElement) ifTrue:[^ true].
-    ].
-    ^ false
-
-    "Modified (comment): / 30-04-2016 / 17:10:34 / cg"
-!
-
-includesKey:aKey
-    ^ self subclassResponsibility
-
-    "Created: / 03-10-2018 / 13:13:31 / Claus Gittinger"
-!
-
 isCollection
     "return true, if the receiver is some kind of collection;
      true is returned here - the method is redefined from Object."
@@ -6284,22 +6374,6 @@
     ^ true
 !
 
-isEmpty
-    "return true, if the receiver is empty"
-
-    ^ self size == 0
-!
-
-isEmptyOrNil
-    "return true if I am nil or an empty collection - true here, if the receiver's size is 0,
-     (from Squeak)"
-
-    ^ self isEmpty
-
-    "Created: / 13.11.2001 / 13:17:12 / cg"
-    "Modified: / 13.11.2001 / 13:28:35 / cg"
-!
-
 isNilOrEmptyCollection
     "return true if I am nil or an empty collection - false here.
      Obsolete, use isEmptyOrNil."
@@ -6363,82 +6437,6 @@
 
     ^ false
 
-!
-
-notEmpty
-    "return true, if the receiver is not empty"
-
-    ^ self isEmpty not
-!
-
-notEmptyOrNil
-    "Squeak compatibility:
-     return true if I am neither nil nor an empty collection."
-
-    ^ self notEmpty
-!
-
-occurrencesOf:anElement
-    "return the number of occurrences of the argument, anElement in
-     the receiver. Uses #= (i.e. equality) compare."
-
-    |count "{ Class: SmallInteger }" |
-
-    count := 0.
-    self do:[:element |
-        (anElement = element) ifTrue:[
-            count := count + 1
-        ].
-    ].
-    ^ count
-!
-
-occurrencesOfAny:aCollectionOfElements
-    "return the number of occurrences of any in aCollectionOfElements in the receiver.
-     Uses #= (i.e. equality) compare.
-     Should be redefined in subclass(es) if ever used heavily."
-
-    |count "{ Class: SmallInteger }" |
-
-    count := 0.
-    aCollectionOfElements do:[:element |
-        count := count + (self occurrencesOf:element)
-    ].
-    ^ count
-
-    "
-     #(1 4 6 8 4 1) occurrencesOfAny:#(1 4)
-     #(1 4 6 8 4 1) occurrencesOfAny:#(2 5)
-     'hello world' occurrencesOfAny:'hel'
-    "
-!
-
-sameValuesComputedBy:aBlock
-    "true if aBlock answers equal values for all elements of the receiver"
-
-    |first valueForFirstElement|
-
-    first := true.
-    self do:[:each |
-        first ifTrue:[
-            first := false.
-            valueForFirstElement := aBlock value:each.
-        ] ifFalse:[
-            valueForFirstElement = (aBlock value:each) ifFalse:[
-                ^ false.
-            ].
-        ].
-    ].
-    ^ true
-
-    "
-     #(1 2 3 5 6 7 8 9) sameValuesComputedBy:[:el | el even]
-     #(1 1 1 1 1 1) sameValuesComputedBy:[:el | el even]
-     #(1 1 1.0 1.0 1) sameValuesComputedBy:[:el | el even]
-     #(1 3 3 15 1) sameValuesComputedBy:[:el | el even]
-    "
-
-    "Created: / 21-12-2011 / 15:59:19 / cg"
 ! !
 
 !Collection methodsFor:'tracing'!