<div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote">2017-11-30 21:57 GMT+01:00  <span dir="ltr"><<a href="mailto:commits@source.squeak.org" target="_blank">commits@source.squeak.org</a>></span>:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Nicolas Cellier uploaded a new version of Collections to project The Trunk:<br>
<a href="http://source.squeak.org/trunk/Collections-nice.771.mcz" rel="noreferrer" target="_blank">http://source.squeak.org/<wbr>trunk/Collections-nice.771.mcz</a><br>
<br>
==================== Summary ====================<br>
<br>
Name: Collections-nice.771<br>
Author: nice<br>
Time: 30 November 2017, 9:57:27.873964 pm<br>
UUID: d8b64711-6119-429b-b3f5-<wbr>259b46ef864b<br>
Ancestors: Collections-nice.770<br>
<br>
Fix awfully broken CharacterSetComplement select:/reject:<br>
<br>
If we want to select:/reject:, we must not only enumerate the absent characters, but rather all the characters in the complement.<br>
<br>
That's way two many, thus we prefer to do it with a LazyCharacterSet, anything else is unfeasible (we don't even know the upper limit of the set of characters...).<br>
<br>
Introduce an AbstractCharacterSet superclass of all the CharacterSet family in order to begin factoring some behavior.<br>
<br>
TODO: we should better rename<br>
CharacterSet -> ByteCharacterSet<br>
AbstractCharacterSet -> CharacterSet.<br>
<br>
We delay this quite technical operation, because we don't want to break existing instances, AND we want to redirect (Byte)CharacterSet references to (Abstract)CharacterSet, the Abstract one becoming a factory.<br>
<br>
=============== Diff against Collections-nice.770 ===============<br>
<br>
Item was added:<br>
+ Collection subclass: #AbstractCharacterSet<br>
+       instanceVariableNames: ''<br>
+       classVariableNames: ''<br>
+       poolDictionaries: ''<br>
+       category: 'Collections-Support'!<br>
<br>
Item was added:<br>
+ ----- Method: AbstractCharacterSet>><wbr>byteArrayMap (in category 'accessing') -----<br>
+ byteArrayMap<br>
+       ^self subclassReponsibility!<br>
<br>
Item was added:<br>
+ ----- Method: AbstractCharacterSet>><wbr>findFirstInByteString:<wbr>startingAt: (in category 'enumerating') -----<br>
+ findFirstInByteString: aByteString startingAt: startIndex<br>
+       "Double dispatching: since we know this is a ByteString, we can use a superfast primitive using a ByteArray map with 0 slots for byte characters not included and 1 for byte characters included in the receiver."<br>
+       ^ByteString<br>
+               findFirstInString: aByteString<br>
+               inSet: self byteArrayMap<br>
+               startingAt: startIndex!<br>
<br>
Item was added:<br>
+ ----- Method: AbstractCharacterSet>><wbr>occurrencesOf: (in category 'enumerating') -----<br>
+ occurrencesOf: anObject<br>
+       "Answer how many of the receiver's elements are equal to anObject. Optimized version."<br>
+<br>
+       (self includes: anObject) ifTrue: [ ^1 ].<br>
+       ^0!<br>
<br>
Item was added:<br>
+ ----- Method: AbstractCharacterSet>><wbr>removeAll (in category 'removing') -----<br>
+ removeAll<br>
+       self becomeForward: CharacterSet new!<br>
<br>
Item was changed:<br>
+ AbstractCharacterSet subclass: #CharacterSet<br>
- Collection subclass: #CharacterSet<br>
        instanceVariableNames: 'map tally'<br>
        classVariableNames: 'CrLf NonSeparators Separators'<br>
        poolDictionaries: ''<br>
        category: 'Collections-Support'!<br>
<br>
  !CharacterSet commentStamp: '<historical>' prior: 0!<br>
  A set of characters.  Lookups for inclusion are very fast.!<br>
<br>
Item was changed:<br>
+ ----- Method: CharacterSet>>= (in category 'comparing') -----<br>
- ----- Method: CharacterSet>>= (in category 'comparison') -----<br>
  = anObject<br>
<br>
        self species == anObject species ifFalse: [ ^false ].<br>
        anObject size = tally ifFalse: [ ^false ].<br>
        ^self byteArrayMap = anObject byteArrayMap!<br>
<br>
Item was changed:<br>
+ ----- Method: CharacterSet>>add: (in category 'adding') -----<br>
- ----- Method: CharacterSet>>add: (in category 'collection ops') -----<br>
  add: aCharacter<br>
        "I automatically become a WideCharacterSet if you add a wide character to myself"<br>
<br>
        | index |<br>
        (index := aCharacter asInteger + 1) <= 256 ifFalse: [<br>
                | wide |<br>
                wide := WideCharacterSet new.<br>
                wide addAll: self.<br>
                wide add: aCharacter.<br>
                self becomeForward: wide.<br>
                ^aCharacter ].<br>
        (map at: index) = 1 ifFalse: [<br>
                map at: index put: 1.<br>
                tally := tally + 1 ].<br>
        ^aCharacter!<br>
<br>
Item was changed:<br>
+ ----- Method: CharacterSet>>do: (in category 'enumerating') -----<br>
- ----- Method: CharacterSet>>do: (in category 'collection ops') -----<br>
  do: aBlock<br>
        "evaluate aBlock with each character in the set"<br>
<br>
        | index |<br>
        tally >= 128 ifTrue: [ "dense"<br>
                index := 0.<br>
                [ (index := index + 1) <= 256 ] whileTrue: [<br>
                        (map at: index) = 1 ifTrue: [<br>
                                aBlock value: (Character value: index - 1) ] ].<br>
                ^self ].<br>
        "sparse"<br>
        index := 0.<br>
        [ (index := map indexOf: 1 startingAt: index + 1) = 0 ] whileFalse: [<br>
                aBlock value: (Character value: index - 1) ].<br>
        !<br>
<br>
Item was changed:<br>
+ ----- Method: CharacterSet>><wbr>findFirstInByteString:<wbr>startingAt: (in category 'enumerating') -----<br>
- ----- Method: CharacterSet>><wbr>findFirstInByteString:<wbr>startingAt: (in category 'collection ops') -----<br>
  findFirstInByteString: aByteString startingAt: startIndex<br>
        "Double dispatching: since we know this is a ByteString, we can use a superfast primitive using a ByteArray map with 0 slots for byte characters not included and 1 for byte characters included in the receiver."<br>
        ^ByteString<br>
                findFirstInString: aByteString<br>
                inSet: self byteArrayMap<br>
                startingAt: startIndex!<br>
<br>
Item was changed:<br>
+ ----- Method: CharacterSet>>hash (in category 'comparing') -----<br>
- ----- Method: CharacterSet>>hash (in category 'comparison') -----<br>
  hash<br>
        ^self byteArrayMap hash!<br>
<br>
Item was changed:<br>
+ ----- Method: CharacterSet>>includes: (in category 'testing') -----<br>
- ----- Method: CharacterSet>>includes: (in category 'collection ops') -----<br>
  includes: anObject<br>
<br>
        | index |<br>
        anObject isCharacter ifFalse: [ ^false ].<br>
        (index := anObject asInteger + 1) > 256 ifTrue: [ ^false ].<br>
        ^(map at: index) > 0!<br>
<br>
Item was removed:<br>
- ----- Method: CharacterSet>>occurrencesOf: (in category 'enumerating') -----<br>
- occurrencesOf: anObject<br>
-       "Answer how many of the receiver's elements are equal to anObject. Optimized version."<br>
-<br>
-       (self includes: anObject) ifTrue: [ ^1 ].<br>
-       ^0!<br>
<br>
Item was changed:<br>
+ ----- Method: CharacterSet>>remove: (in category 'removing') -----<br>
- ----- Method: CharacterSet>>remove: (in category 'collection ops') -----<br>
  remove: aCharacter<br>
<br>
        ^self remove: aCharacter ifAbsent: aCharacter!<br>
<br>
Item was changed:<br>
+ ----- Method: CharacterSet>>remove:ifAbsent: (in category 'removing') -----<br>
- ----- Method: CharacterSet>>remove:ifAbsent: (in category 'collection ops') -----<br>
  remove: aCharacter ifAbsent: aBlock<br>
<br>
        | index |<br>
        (index := aCharacter asciiValue + 1) <= 256 ifFalse: [ ^aBlock value ].<br>
        (map at: index) = 0 ifTrue: [ ^aBlock value ].<br>
        map at: index put: 0.<br>
        tally := tally - 1.<br>
        ^aCharacter!<br>
<br>
Item was changed:<br>
+ ----- Method: CharacterSet>>size (in category 'accessing') -----<br>
- ----- Method: CharacterSet>>size (in category 'collection ops') -----<br>
  size<br>
<br>
        ^tally!<br>
<br>
Item was changed:<br>
+ ----- Method: CharacterSet>>species (in category 'comparing') -----<br>
- ----- Method: CharacterSet>>species (in category 'comparison') -----<br>
  species<br>
        ^CharacterSet!<br>
<br>
Item was changed:<br>
+ AbstractCharacterSet subclass: #CharacterSetComplement<br>
- Collection subclass: #CharacterSetComplement<br>
        instanceVariableNames: 'absent byteArrayMapCache'<br>
        classVariableNames: ''<br>
        poolDictionaries: ''<br>
        category: 'Collections-Support'!<br>
<br>
  !CharacterSetComplement commentStamp: 'nice 8/31/2008 14:53' prior: 0!<br>
  CharacterSetComplement is a space efficient implementation of (CharacterSet complement) taking care of WideCharacter (code > 255)<br>
<br>
  However, it will maintain a byteArrayMap for character <= 255 in a cache keeping<br>
<br>
  instance variables:<br>
        absent <CharacterSet> contains character that are not in the set (i.e. my complement)<br>
        byteArrayMapCache <ByteArray | nil> cache this information because it has to be used in tight loops where efficiency matters!<br>
<br>
Item was changed:<br>
+ ----- Method: CharacterSetComplement>>add: (in category 'adding') -----<br>
- ----- Method: CharacterSetComplement>>add: (in category 'collection ops') -----<br>
  add: aCharacter<br>
        "a character is present if not absent, so adding a character is removing it from the absent"<br>
<br>
        (absent includes: aCharacter)<br>
                ifTrue:<br>
                        [byteArrayMapCache := nil.<br>
                        absent remove: aCharacter].<br>
        ^ aCharacter!<br>
<br>
Item was changed:<br>
+ ----- Method: CharacterSetComplement>>do: (in category 'enumerating') -----<br>
- ----- Method: CharacterSetComplement>>do: (in category 'collection ops') -----<br>
  do: aBlock<br>
        "evaluate aBlock with each character in the set.<br>
        don't do it, there are too many..."<br>
<br>
        self shouldNotImplement!<br>
<br>
Item was changed:<br>
+ ----- Method: CharacterSetComplement>><wbr>findFirstInByteString:<wbr>startingAt: (in category 'enumerating') -----<br>
- ----- Method: CharacterSetComplement>><wbr>findFirstInByteString:<wbr>startingAt: (in category 'collection ops') -----<br>
  findFirstInByteString: aByteString startingAt: startIndex<br>
        "Double dispatching: since we know this is a ByteString, we can use a superfast primitive using a ByteArray map with 0 slots for byte characters not included and 1 for byte characters included in the receiver."<br>
        ^ByteString<br>
                findFirstInString: aByteString<br>
                inSet: self byteArrayMap<br>
                startingAt: startIndex!<br>
<br>
Item was changed:<br>
+ ----- Method: CharacterSetComplement>><wbr>includes: (in category 'testing') -----<br>
- ----- Method: CharacterSetComplement>><wbr>includes: (in category 'collection ops') -----<br>
  includes: anObject<br>
<br>
        anObject isCharacter ifFalse: [ ^false ].<br>
        (absent includes: anObject) ifTrue: [ ^false ].<br>
        ^true!<br>
<br>
Item was removed:<br>
- ----- Method: CharacterSetComplement>><wbr>occurrencesOf: (in category 'enumerating') -----<br>
- occurrencesOf: anObject<br>
-       "Answer how many of the receiver's elements are equal to anObject. Optimized version."<br>
-<br>
-       (self includes: anObject) ifTrue: [ ^1 ].<br>
-       ^0!<br>
<br>
Item was changed:<br>
+ ----- Method: CharacterSetComplement>><wbr>reject: (in category 'enumerating') -----<br>
- ----- Method: CharacterSetComplement>><wbr>reject: (in category 'collection ops') -----<br>
  reject: aBlock<br>
+       ^LazyCharacterSet including: [:c | (absent includes: c) not and: [(aBlock value: c) not]]!<br>
-       "Implementation note: rejecting present is selecting absent"<br>
-<br>
-       ^(absent select: aBlock) complement!<br>
<br>
Item was changed:<br>
+ ----- Method: CharacterSetComplement>><wbr>remove: (in category 'removing') -----<br>
- ----- Method: CharacterSetComplement>><wbr>remove: (in category 'collection ops') -----<br>
  remove: aCharacter<br>
        "This means aCharacter is now absent from myself.<br>
        It must be added to my absent."<br>
<br>
        byteArrayMapCache := nil.<br>
        ^absent add: aCharacter!<br>
<br>
Item was changed:<br>
+ ----- Method: CharacterSetComplement>><wbr>remove:ifAbsent: (in category 'removing') -----<br>
- ----- Method: CharacterSetComplement>><wbr>remove:ifAbsent: (in category 'collection ops') -----<br>
  remove: aCharacter ifAbsent: aBlock<br>
        (self includes: aCharacter) ifFalse: [^aBlock value].<br>
        ^self remove: aCharacter!<br>
<br>
Item was removed:<br>
- ----- Method: CharacterSetComplement>><wbr>removeAll (in category 'collection ops') -----<br>
- removeAll<br>
-<br>
-       self becomeForward: CharacterSet new!<br>
<br>
Item was changed:<br>
+ ----- Method: CharacterSetComplement>><wbr>select: (in category 'enumerating') -----<br>
- ----- Method: CharacterSetComplement>><wbr>select: (in category 'collection ops') -----<br>
  select: aBlock<br>
+       ^LazyCharacterSet including: [:c | (absent includes: c) not and: [aBlock value: c]]!<br>
-       "Implementation note: selecting present is rejecting absent"<br>
-<br>
-       ^(absent reject: aBlock) complement!<br>
<br>
Item was removed:<br>
- ----- Method: CharacterSetComplement>>size (in category 'collection ops') -----<br>
- size<br>
-       "Is this 2**32-absent size ?"<br>
-<br>
-       ^self shouldNotImplement!<br>
<br>
Item was added:<br>
+ ----- Method: Interval>>copyFrom:to: (in category 'copying') -----<br>
+ copyFrom: startIndex to: stopIndex<br>
+       stopIndex < startIndex ifTrue: [^self copyEmpty].<br>
+       ^(self at: startIndex) to: (self at: stopIndex) by: step!<br>
<br></blockquote><div><br></div><div>Arghh, sorry, the Interval>>copyFrom:to: was a totally unrelated experiment</div><div><br></div><div>I think it is a good change, but it might break some tests and should have better gone in its own change set/commit.</div><div><br></div><div>By now I let it there, but if any one bark, I will revert.<br></div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
Item was added:<br>
+ AbstractCharacterSet subclass: #LazyCharacterSet<br>
+       instanceVariableNames: 'block byteArrayMapCache'<br>
+       classVariableNames: ''<br>
+       poolDictionaries: ''<br>
+       category: 'Collections-Support'!<br>
+<br>
+ !LazyCharacterSet commentStamp: 'nice 11/30/2017 21:40' prior: 0!<br>
+ A LazyCharacterSet is a kind of CharacterSet which does not know in advance which Character it contains or not.<br>
+ If will lazily evaluate a block on demand if ever one ask whether it includes: a character.<br>
+ It is not feasible to enumerate a LazyCharacterSet, because there are way too many characters.<br>
+<br>
+ Instance Variables<br>
+       block:          <BlockContext | Symbol><br>
+       byteArrayMapCache:              <ByteArray | nil><br>
+<br>
+ block<br>
+       - a valuable, answering either true or false when sent the message value: - true means that this set includes the character passed as value: argument.<br>
+<br>
+ byteArrayMapCache<br>
+       - a cache holding 0 or 1 for the first 256 character codes - 0 meaning not included, 1 included. This is used in some priitives<br>
+ !<br>
<br>
Item was added:<br>
+ ----- Method: LazyCharacterSet class>>including: (in category 'instance creation') -----<br>
+ including: aBlock<br>
+       "Create the set of Character for which aBlock evaluates to true"<br>
+       ^self class new block: aBlock!<br>
<br>
Item was added:<br>
+ ----- Method: LazyCharacterSet>>add: (in category 'adding') -----<br>
+ add: aCharacter<br>
+       self block: [:c | c = aCharacter or: [block value: c]].<br>
+       ^aCharacter!<br>
<br>
Item was added:<br>
+ ----- Method: LazyCharacterSet>>addAll: (in category 'adding') -----<br>
+ addAll: aCollection<br>
+       self block: [:c | (aCollection includes: c) or: [block value: c]].<br>
+       ^aCollection!<br>
<br>
Item was added:<br>
+ ----- Method: LazyCharacterSet>>block (in category 'accessing') -----<br>
+ block<br>
+       ^block!<br>
<br>
Item was added:<br>
+ ----- Method: LazyCharacterSet>>block: (in category 'accessing') -----<br>
+ block: aValuable<br>
+       "Set the block used to determine if I include a Character or not.<br>
+       aValuable is an object that shoud answer true or false when sent value:"<br>
+<br>
+       byteArrayMapCache := nil.<br>
+       ^block := aValuable!<br>
<br>
Item was added:<br>
+ ----- Method: LazyCharacterSet>>byteArrayMap (in category 'accessing') -----<br>
+ byteArrayMap<br>
+       "return a ByteArray mapping each ascii value to a 1 if that ascii value is in the set, and a 0 if it isn't.  Intended for use by primitives only"<br>
+<br>
+       ^byteArrayMapCache ifNil: [byteArrayMapCache := (0 to: 255) collect: [:i | self includes: (Character value: i)]]!<br>
<br>
Item was added:<br>
+ ----- Method: LazyCharacterSet>>complement (in category 'converting') -----<br>
+ complement<br>
+       ^self class including: [:char | (block value: char) not]!<br>
<br>
Item was added:<br>
+ ----- Method: LazyCharacterSet>>do: (in category 'enumerating') -----<br>
+ do: aBlock<br>
+       "evaluate aBlock with each character in the set.<br>
+       don't do it, there are too many loop..."<br>
+<br>
+       self shouldNotImplement!<br>
<br>
Item was added:<br>
+ ----- Method: LazyCharacterSet>>includes: (in category 'testing') -----<br>
+ includes: aCharacter<br>
+       ^block value: aCharacter!<br>
<br>
Item was added:<br>
+ ----- Method: LazyCharacterSet>>reject: (in category 'enumerating') -----<br>
+ reject: aBlock<br>
+       ^self class including: [:char | (aBlock value: char) not and: [block value: char]]!<br>
<br>
Item was added:<br>
+ ----- Method: LazyCharacterSet>>remove: (in category 'removing') -----<br>
+ remove: aCharacter<br>
+       self block: [:c | (c = aCharacter) not and: [block value: c]].<br>
+       ^aCharacter!<br>
<br>
Item was added:<br>
+ ----- Method: LazyCharacterSet>>remove:<wbr>ifAbsent: (in category 'removing') -----<br>
+ remove: aCharacter ifAbsent: aBlock<br>
+       (self includes: aCharacter) ifFalse: [^aBlock value].<br>
+       ^self remove: aCharacter!<br>
<br>
Item was added:<br>
+ ----- Method: LazyCharacterSet>>removeAll: (in category 'removing') -----<br>
+ removeAll: aCollection<br>
+       self block: [:c | (aCollection include: c) not and: [block value: c]].<br>
+       ^aCollection!<br>
<br>
Item was added:<br>
+ ----- Method: LazyCharacterSet>>select: (in category 'enumerating') -----<br>
+ select: aBlock<br>
+       ^self class including: [:char | (block value: char) and: [aBlock value: char]]!<br>
<br>
Item was changed:<br>
+ AbstractCharacterSet subclass: #WideCharacterSet<br>
- Collection subclass: #WideCharacterSet<br>
        instanceVariableNames: 'map byteArrayMap bitsetCapacity highBitsShift lowBitsMask'<br>
        classVariableNames: ''<br>
        poolDictionaries: ''<br>
        category: 'Collections-Support'!<br>
<br>
  !WideCharacterSet commentStamp: 'nice 12/10/2009 19:17' prior: 0!<br>
  WideCharacterSet is used to store a Set of WideCharacter with fast access and inclusion test.<br>
<br>
  Implementation should be efficient in memory if sets are sufficently sparse.<br>
<br>
  Wide Characters are at most 32bits.<br>
  We split them into 16 highBits and 16 lowBits.<br>
<br>
  map is a dictionary key: 16 highBits value: map of 16 lowBits.<br>
<br>
  Maps of lowBits  are stored as arrays of bits in a ByteArray.<br>
  If a bit is set to 1, this indicate that corresponding character is present.<br>
  8192 bytes are necessary in each lowmap.<br>
  Empty lowmap are removed from the map Dictionary.<br>
<br>
  A byteArrayMap is maintained in parallel with map for fast handling of ByteString.<br>
  (byteArrayMap at: i+1) = 0 means that character of asciiValue i is absent, = 1 means present.!<br>
<br>
Item was changed:<br>
+ ----- Method: WideCharacterSet>>add: (in category 'adding') -----<br>
- ----- Method: WideCharacterSet>>add: (in category 'collection ops') -----<br>
  add: aCharacter<br>
<br>
        | value highBits lowBits |<br>
        (value := aCharacter asInteger) < 256 ifTrue: [<br>
                byteArrayMap at: value + 1 put: 1 ].<br>
        highBits := value bitShift: highBitsShift.<br>
        lowBits := value bitAnd: lowBitsMask.<br>
        (map at: highBits ifAbsentPut: [ Bitset new: bitsetCapacity ])<br>
                setBitAt: lowBits.<br>
        ^aCharacter!<br>
<br>
Item was changed:<br>
+ ----- Method: WideCharacterSet>>do: (in category 'enumerating') -----<br>
- ----- Method: WideCharacterSet>>do: (in category 'collection ops') -----<br>
  do: aBlock<br>
<br>
        map keysAndValuesDo: [ :index :bitset |<br>
                | highBits |<br>
                highBits := index * bitsetCapacity.<br>
                bitset do: [ :lowBits |<br>
                        aBlock value: (Character value: highBits + lowBits) ] ]!<br>
<br>
Item was changed:<br>
+ ----- Method: WideCharacterSet>><wbr>findFirstInByteString:<wbr>startingAt: (in category 'enumerating') -----<br>
- ----- Method: WideCharacterSet>><wbr>findFirstInByteString:<wbr>startingAt: (in category 'collection ops') -----<br>
  findFirstInByteString: aByteString startingAt: startIndex<br>
        "Double dispatching: since we know this is a ByteString, we can use a superfast primitive using a ByteArray map with 0 slots for byte characters not included and 1 for byte characters included in the receiver."<br>
<br>
        ^ByteString<br>
                findFirstInString: aByteString<br>
                inSet: byteArrayMap<br>
                startingAt: startIndex!<br>
<br>
Item was changed:<br>
+ ----- Method: WideCharacterSet>>includes: (in category 'testing') -----<br>
- ----- Method: WideCharacterSet>>includes: (in category 'collection ops') -----<br>
  includes: anObject<br>
<br>
        | value |<br>
        anObject isCharacter ifFalse: [ ^false ].<br>
        (value := anObject asInteger) < 256 ifTrue: [<br>
                ^(byteArrayMap at: value + 1) ~= 0 ].<br>
        ^((map at: (value bitShift: highBitsShift) ifAbsent: nil) ifNil: [ ^false ])<br>
                includes: (value bitAnd: lowBitsMask)!<br>
<br>
Item was removed:<br>
- ----- Method: WideCharacterSet>><wbr>occurrencesOf: (in category 'enumerating') -----<br>
- occurrencesOf: anObject<br>
-       "Answer how many of the receiver's elements are equal to anObject. Optimized version."<br>
-<br>
-       (self includes: anObject) ifTrue: [ ^1 ].<br>
-       ^0!<br>
<br>
Item was changed:<br>
+ ----- Method: WideCharacterSet>>remove: (in category 'removing') -----<br>
- ----- Method: WideCharacterSet>>remove: (in category 'collection ops') -----<br>
  remove: aCharacter<br>
        "Don't signal an error when aCharacter is not present."<br>
<br>
        ^self remove: aCharacter ifAbsent: aCharacter!<br>
<br>
Item was changed:<br>
+ ----- Method: WideCharacterSet>>remove:<wbr>ifAbsent: (in category 'removing') -----<br>
- ----- Method: WideCharacterSet>>remove:<wbr>ifAbsent: (in category 'collection ops') -----<br>
  remove: aCharacter ifAbsent: aBlock<br>
<br>
        | value highBits lowBits bitset |<br>
        (value := aCharacter asInteger) < 256 ifTrue: [<br>
                (byteArrayMap at: value + 1) = 0 ifTrue: [ ^aBlock value ].<br>
                byteArrayMap at: value + 1 put: 0 ].<br>
        highBits := value bitShift: highBitsShift.<br>
        lowBits := value bitAnd: lowBitsMask.<br>
        bitset := (map at: highBits ifAbsent: nil) ifNil: [ ^aBlock value ].<br>
        ((bitset clearBitAt: lowBits) and: [ bitset size = 0 ]) ifTrue: [<br>
                map removeKey: highBits ].<br>
        ^aCharacter!<br>
<br>
Item was changed:<br>
+ ----- Method: WideCharacterSet>>removeAll (in category 'removing') -----<br>
- ----- Method: WideCharacterSet>>removeAll (in category 'collection ops') -----<br>
  removeAll<br>
<br>
        map isEmpty ifTrue: [ ^self ].<br>
        map removeAll.<br>
        byteArrayMap atAllPut: 0!<br>
<br>
Item was changed:<br>
+ ----- Method: WideCharacterSet>>size (in category 'accessing') -----<br>
- ----- Method: WideCharacterSet>>size (in category 'collection ops') -----<br>
  size<br>
<br>
        ^map detectSum: [ :each | each size ]!<br>
<br>
<br>
</blockquote></div><br></div></div>