Module: Weak::Set::WeakKeysWithDelete

Defined in:
lib/weak/set/weak_keys_with_delete.rb

Overview

This Weak::Set strategy targets Ruby >= 3.3.0. Older Ruby versions require additional indirections implemented in WeakKeys:

Ruby's ObjectSpace::WeakMap uses weak keys and weak values so that either the key or the value can be independently garbage collected. If either of them vanishes, the entry is removed.

The ObjectSpace::WeakMap also allows to delete entries. This allows us to directly use the ObjectSpace::WeakMap as a storage the same way a ::Set uses a Hash object object as storage.

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.usable?Bool

Checks if this strategy is usable for the current Ruby version.

Returns:

  • (Bool)

    truethy for Ruby (aka. MRI, aka. YARV) >= 3.3.0, falsey otherwise



29
30
31
32
# File 'lib/weak/set/weak_keys_with_delete.rb', line 29

def self.usable?
  RUBY_ENGINE == "ruby" &&
    ObjectSpace::WeakMap.instance_methods.include?(:delete)
end

Instance Method Details

#add(obj) ⇒ self

Adds the given object to the weak set and return self. Use Weak::Set#merge to add many elements at once.

In contrast to other "regular" objects, we will not retain a strong reference to the added object. Unless some other live objects still references the object, it will eventually be garbage-collected.

Examples:

Weak::Set[1, 2].add(3)                #=> #<Weak::Set {1, 2, 3}>
Weak::Set[1, 2].add([3, 4])           #=> #<Weak::Set {1, 2, [3, 4]}>
Weak::Set[1, 2].add(2)                #=> #<Weak::Set {1, 2}>

Parameters:

  • obj (Object)

    an object

Returns:

  • (self)


35
36
37
38
# File 'lib/weak/set/weak_keys_with_delete.rb', line 35

def add(obj)
  @map[obj] = true
  self
end

#clearself

Removes all elements and returns self

Returns:

  • (self)


41
42
43
44
# File 'lib/weak/set/weak_keys_with_delete.rb', line 41

def clear
  @map = ObjectSpace::WeakMap.new
  self
end

#delete?(obj) ⇒ self?

Note:

Weak::Set does not test member equality with == or eql?. Instead, it always checks strict object equality, so that, e.g., different strings are not considered equal, even if they may contain the same string content.

Deletes the given object from self and returns self if it was present in the set. If the object was not in the set, returns nil.

Parameters:

  • obj (Object)

Returns:

  • (self, nil)

    self if the given object was deleted from the set or nil if the object was not part of the set



47
48
49
50
51
52
# File 'lib/weak/set/weak_keys_with_delete.rb', line 47

def delete?(obj)
  # `ObjectSpace::WeakMap#delete` returns the value if it was removed. As
  # we set it to true, `ObjectSpace::WeakMap#delete` returns either true
  # or nil here.
  self if @map.delete(obj)
end

#each {|element| ... } ⇒ self, Enumerator

Calls the given block once for each live element in self, passing that element as a parameter. Returns the weak set itself.

If no block is given, an Enumerator is returned instead.

Yields:

  • (element)

    calls the given block once for each element in self

Yield Parameters:

  • element (Object)

    the yielded value

Returns:

  • (self, Enumerator)

    self if a block was given or an Enumerator if no block was given.



55
56
57
58
59
60
# File 'lib/weak/set/weak_keys_with_delete.rb', line 55

def each(&block)
  return enum_for(__method__) { size } unless block_given?

  @map.keys.each(&block)
  self
end

#include?(obj) ⇒ Bool

Note:

Weak::Set does not test member equality with == or eql?. Instead, it always checks strict object equality, so that, e.g., different strings are not considered equal, even if they may contain the same string content.

Returns true if the given object is included in self, false otherwise.

Parameters:

  • obj (Object)

    an object

Returns:

  • (Bool)

    true if the given object is included in self, false otherwise



63
64
65
# File 'lib/weak/set/weak_keys_with_delete.rb', line 63

def include?(obj)
  @map.key?(obj)
end

#pruneself

Cleanup data structures from the set to remove data associated with deleted or garbage collected elements. This method may be called automatically for some Weak::Set operations.

Returns:

  • (self)


68
69
70
# File 'lib/weak/set/weak_keys_with_delete.rb', line 68

def prune
  self
end

#replace(enum) ⇒ self

Replaces the contents of self with the contents of the given enumerable object and returns self.

Examples:

set = Weak::Set[1, :c, :s]        #=> #<Weak::Set {1, :c, :s}>
set.replace([1, 2])               #=> #<Weak::Set {1, 2}>
set                               #=> #<Weak::Set {1, 2}>

Parameters:

Returns:

  • (self)


73
74
75
76
77
78
79
80
81
# File 'lib/weak/set/weak_keys_with_delete.rb', line 73

def replace(enum)
  map = ObjectSpace::WeakMap.new
  do_with_enum(enum) do |obj|
    map[obj] = true
  end
  @map = map

  self
end

#sizeInteger

Returns the number of live elements in self.

Returns:

  • (Integer)

    the number of live elements in self



84
85
86
# File 'lib/weak/set/weak_keys_with_delete.rb', line 84

def size
  @map.size
end

#to_aArray

Note:

The order of elements on the returned Array is non-deterministic. We do not preserve preserve insertion order.

Returns the live elements contained in self as an Array.

Returns:

  • (Array)

    the live elements contained in self as an Array



89
90
91
# File 'lib/weak/set/weak_keys_with_delete.rb', line 89

def to_a
  @map.keys
end