- live browsing of Self object memory -

lobby traitsuniversalSetOrDictionary

Ordinary hash-table-based sets and dictionaries use an
emptyMarker and a removedMarker to indicate the absence
of a key. This means that those markers cannot be used
as keys in an ordinary set or dictionary.

I am a set or dictionary that can hold those markers
(though I'm a bit slower than ordinary sets and

CopyDowns: vector

CreatorPath: traits universalSetOrDictionary

Module: universalSetAndDictionary

comparisonTraits = ( mySetOrDictionary comparisonTraits)
unitTests = traits universalSetOrDictionary unitTests


size = ( mySetOrDictionary size + includesMarker asInteger)
valueForMarker: =
    includesMarker: true.


copyFor:Marker: =
    ((clone mySetOrDictionary: aSetOrDictionary)
                       marker: m) initialize)
initialize =
    includesMarker: false.
unsafe_copy = ( clone mySetOrDictionary: mySetOrDictionary copy)

fast accessing and adding

if:IsPresentAnd:Put:AndDo:IfAbsentAnd:Put:AndDo: =
    marker == k ifTrue: [
      ^ includesMarker
          ifTrue: [
               ifTrue: [ | newValue |
                         newValue:  replacementValueBlock value: valueForMarker With: marker.
                         valueForMarker: newValue.
                         presentActionBlock value: newValue       With: marker]
                False: [ presentActionBlock value: valueForMarker With: marker] ]
           False: [
               ifTrue: [ absentActionBlock value: valueForMarker:  newValueBlock value: k ]
                False: [ absentActionBlock value:                                       k ]]

    mySetOrDictionary if: k
            IsPresentAnd: doPresentPut
                     Put: replacementValueBlock
                   AndDo: presentActionBlock
             IfAbsentAnd: doAbsentPut
                     Put: newValueBlock
                   AndDo: absentActionBlock)
if collection contains k, invoke replacementValueBlock with arg old value and replace contents at k with result of replacementValueBlock. Then invoke presentActionBlock with arg new value. If k is absent, add result of evaluating newValueBlock at key k (for dicts) and invoke absentActionBlock with new value.


unsafe_do: =
    includesMarker ifTrue: [b value: valueForMarker With: marker].
    mySetOrDictionary unsafe_do: b.
unsafe_with:Do: =
    includesMarker ifFalse: [^ mySetOrDictionary unsafe_with: c Do: b ].

    "Double-dispatch to enable faster implementation in the case where
     c is another universalSetOrDictionary (or some other collection
     with a linked-list kind of structure)."
    c unsafe_with: mySetOrDictionary Do: b FirstKey: marker FirstValue: valueForMarker)
unsafe_with:Do:FirstKey:FirstValue: =
    "Double-dispatch from another universalSetOrDictionary. Iterate in
     parallel over the other collection and this one, treating firstK1
     and firstV1 as the first key and value from the other collection.
     If we both include our marker, we can yield the two markers
     together, rather than fall back on the default implementation
     back in traits collection."

    includesMarker ifTrue: [
      b value: firstV1 With: valueForMarker With: firstK1 With: marker.
      c1 with: mySetOrDictionary Do: b.
    ] False: [
      mySetOrDictionary unsafe_with: c1 Do: b FirstKey: firstK1 FirstValue: firstV1.


removeFirstIfAbsent: =
    includesMarker ifTrue: [^ removeValueForMarker].
    mySetOrDictionary removeFirstIfAbsent: absentBlk)
Remove an arbitrary element from the set or dictionary. Return the removed element (not the key).
removeKey:IfAbsent: =
    marker == k ifTrue: [^ includesMarker ifTrue: [removeValueForMarker] False: b].
    mySetOrDictionary removeKey: k IfAbsent: b)
removeValueForMarker =
( | oldValue |
    includesMarker ifFalse: [error: 'marker is not present'].
    oldValue: valueForMarker.
    valueForMarker: nil. "Necessary to avoid memory leaks."
    includesMarker: false.
unsafe_removeAll =
    mySetOrDictionary: mySetOrDictionary copyRemoveAll.


unsafe_desiredMinCapacity: =
    mySetOrDictionary unsafe_desiredMinCapacity: s.