Class: Farce::Abstract::Map Abstract

Inherits:
Object
  • Object
show all
Includes:
Enumerable, Internal::Inspect, Internal::MarshalSupport::Map
Defined in:
lib/farce/abstract/map.rb,
lib/farce/integrations/bson.rb,
lib/farce/integrations/cbor.rb,
lib/farce/integrations/psych.rb,
lib/farce/integrations/msgpack.rb,
lib/farce/integrations/shared/to_json.rb,
lib/farce/integrations/active_support/map.rb

Overview

This class is abstract.

Superclass for all maps defined by Farce.

Note:

The supported methods are generally compatible with their Hash counterparts, with the notable exception of ConcurrentMap#update.

A Hash-like collection with slightly reduced functionality to allow for better concurrency models.

Constructors accept a Hash, another map, or an object whose #each yields key/value pairs. Arrays of pairs and enumerators are supported. Initial entries are inserted in source order. Local maps retain the initial entries for reuse in each scope.

dup and clone create independent storage and coordination while sharing keys and stored values. Value modes and key normalization are preserved without transferring values again. Copies of shareable maps remain shareable unless explicitly cloned with freeze: false. Local copies retain the current scope's contents. Other scopes use the original constructor configuration. Lease maps reject copying because resources cannot safely be given independent ownership controls.

Iteration order is implementation-dependent. In particular, insertion order is not guaranteed.

Implementations can compare keys and values either by equality or by identity. Operations accepting a timeout wait at most that many seconds to acquire the access needed for the operation. A timeout must be a finite, non-negative number, nil waits indefinitely.

Direct Known Subclasses

BoundedMap, ConcurrentMap, LeaseMap, TreeMap

BSON Integration collapse

CBOR Integration collapse

ActiveSupport Integration collapse

JSON Integration collapse

Instance Method Summary collapse

Instance Method Details

#[](key) ⇒ BasicObject?

This method is abstract.

Look up a key without waiting for atomic-update access.

Parameters:

  • key (BasicObject) —

    The key to look up.

Returns:

  • (BasicObject, nil) —

    The associated value, or nil if the key is absent.



155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
# File 'lib/farce/abstract/map.rb', line 155

class Map
  include Internal::MarshalSupport::Map
  include Enumerable
  include Internal::Inspect

  # Store a value using the map's assignment operation.
  # Concurrent maps override this method to support timeouts.
  # @param key [BasicObject] the key to store
  # @param value [BasicObject] the value to store
  # @return [BasicObject] `value`
  def store(key, value) = self[key] = value

  # Return a two-element array containing a key and its associated value, if the key is present,
  # or nil if the key is absent.
  # @param key [BasicObject] The key to look up.
  # @return [Array(BasicObject, BasicObject), nil] A two-element `[key, value]` array, or nil if the key is absent.
  def assoc(key)
    value = fetch(key) { return nil }
    [key, value]
  end

  # (see #compare_keys_by_identity?)
  def compare_by_identity? = compare_keys_by_identity?

  # Implements Ruby's [dig interface](https://docs.ruby-lang.org/en/master/language/dig_methods_rdoc.html).
  # @param key [BasicObject] The key to look up.
  # @param rest [Array<BasicObject>] Additional keys to look up in nested maps.
  # @return [BasicObject, nil] The value found at the nested location, or nil if any key is absent or nil.
  def dig(key, *rest)
    value = self[key]
    return value if rest.empty? || value.nil?
    value.dig(*rest)
  end

  # Returns whether the map contains no entries.
  # @return [Boolean] Whether the map is empty.
  def empty? = size.zero?

  # Return the number of entries currently in the map.
  # @return [Integer]
  def length = size

  # Return whether an observed value matches using this map's value comparison setting.
  # Values are unwrapped before comparison. Concurrent changes may make the result stale.
  # @param value [BasicObject] the value to find
  # @return [Boolean]
  def value?(value)
    identity = compare_values_by_identity?
    each_value.any? { |stored| identity ? stored.equal?(value) : stored == value }
  end
  alias has_value? value?

  # Return a matching key using this map's value comparison setting, or nil.
  # The first observed match is returned. No insertion order is guaranteed.
  # @param value [BasicObject] the value to find
  # @return [BasicObject, nil]
  def key(value)
    pair = rassoc(value)
    pair&.first
  end

  # Return an observed key/value pair using this map's value comparison setting, or nil.
  # Values are unwrapped before comparison. Concurrent changes may make the result stale.
  # @param value [BasicObject] the value to find
  # @return [Array, nil]
  def rassoc(value)
    identity = compare_values_by_identity?
    each_pair do |key, stored|
      return [key, stored] if identity ? stored.equal?(value) : stored == value
    end
    nil
  end

  # Alias for {#key?}
  def has_key?(...) = key?(...) # rubocop:disable Naming/PredicatePrefix
  alias member?  has_key?
  alias include? has_key?

  # Fetches the values associated with multiple keys, using the same missing-key behavior as Hash#fetch.
  # @yield [key] Called for each missing key.
  # @yieldparam key [BasicObject] The missing key.
  # @yieldreturn [BasicObject] The value to return for the missing key.
  # @param keys [Array<BasicObject>] The keys to look up.
  # @return [Array<BasicObject>] An array of the associated values.
  def fetch_values(*keys, &) = keys.map { fetch(it, &) }

  # @note
  #   Some maps may still accept non-shareable keys or values, but convert them into shareable representations.
  #   This method will still return `true` for such maps.
  #
  # @return [Boolean] Whether the map requires keys to be Ractor-shareable
  def shareable_keys? = false

  # @return [Boolean] Whether the map requires values to be Ractor-shareable
  def shareable_values? = false

  # Creates a new Array containing the map's key-value pairs as two-element arrays.
  # @return [Array<Array(BasicObject, BasicObject)>>] A new Array of `[key, value]` arrays.
  def to_a = each_pair.to_a

  # Creates a new Hash containing the map's entries.
  # Preserves identity comparison for keys, including when a block transforms entries.
  # @yieldparam key [BasicObject] an existing key
  # @yieldparam value [BasicObject] its value
  # @yieldreturn [Array(BasicObject, BasicObject)] the key and value for the new Hash
  # @return [Hash] A new Hash with the original entries, or the pairs returned by the block.
  def to_h(&) = entries_to_hash(each_pair, &)

  # Support implicit Hash conversion using this map's {#to_h} implementation.
  # @return [Hash] A new Hash containing the map's entries.
  def to_hash = to_h

  # Support hash patterns using the same entries and key comparison as {#to_h}.
  # Like Hash, this returns all entries regardless of the requested keys.
  # @param keys [Array, nil] the optional key hint supplied by Ruby's pattern matcher
  # @return [Hash] A new Hash containing the map's entries.
  def deconstruct_keys(keys) = to_h # rubocop:disable Lint/UnusedMethodArgument

  # Fetches the values associated with multiple keys, returning nil for any missing keys.
  # @param keys [Array<BasicObject>] The keys to look up.
  # @return [Array<BasicObject>] An array of the associated values, with nil for any missing keys.
  def values_at(*keys) = keys.map { self[it] }

  # Some maps reference their keys weakly, automatically dropping entries when a key gets garbage-collected.
  # @return [Boolean] Whether the map uses weak references for keys.
  def weak_keys? = false

  # Some maps reference their values weakly, automatically dropping entries when a value gets garbage-collected.
  # @return [Boolean] Whether the map uses weak references for values.
  def weak_values? = false

  # @return [String] String representation of the map, suitable for debugging.
  def to_s = inspect

  # @api private
  def inspect_with(inspector)
    super do
      yield if block_given?
      inspector.breakable
      inspector.group("{", "}") do
        inspector.breakable ""
        inspector.seplist(self, nil, :each_for_inspect) do |key, value|
          inspector.group { inspect_pair(inspector, key, value) }
        end
      end
    end
  end

  protected

  # Convert a public value to its stored representation.
  # @api private
  def wrap_value(value) = value

  # Convert a stored representation to its public value.
  # @api private
  def unwrap_value(value) = value

  private

  def entries_to_hash(entries, &)
    return entries.to_h(&) unless compare_keys_by_identity?
    hash = {}.compare_by_identity
    entries.each do |key, value|
      if block_given?
        pair = Array.try_convert(yield(key, value))
        raise TypeError, "block must return an Array or respond to #to_ary" unless pair
        raise ArgumentError, "block must return a two-element pair" unless pair.size == 2
        key, value = pair
      end
      hash[key] = value
    end
    hash
  end

  def convert_entries(entries)
    return entries if Map === entries
    if entries.respond_to?(:to_hash)
      entries = Hash.try_convert(entries)
      raise TypeError, "entries must be a Hash or respond to #to_hash" unless entries
    end
    return entries if entries.nil? || entries.respond_to?(:each)
    raise TypeError, "entries must yield key/value pairs with #each"
  end

  def each_for_inspect(&)                 = each(&)
  def inspect_pair(inspector, key, value) = inspector.hash_pair(key, value) { inspect_value(inspector, value) }
  def inspect_value(inspector, ...)       = inspector.object(...)
end

#[]=(key, value) ⇒ BasicObject

This method is abstract.

Associate a value with a key without a timeout.

Parameters:

  • key (BasicObject) —

    The key to store.

  • value (BasicObject) —

    The value to store.

Returns:

  • (BasicObject) —

    value.



155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
# File 'lib/farce/abstract/map.rb', line 155

class Map
  include Internal::MarshalSupport::Map
  include Enumerable
  include Internal::Inspect

  # Store a value using the map's assignment operation.
  # Concurrent maps override this method to support timeouts.
  # @param key [BasicObject] the key to store
  # @param value [BasicObject] the value to store
  # @return [BasicObject] `value`
  def store(key, value) = self[key] = value

  # Return a two-element array containing a key and its associated value, if the key is present,
  # or nil if the key is absent.
  # @param key [BasicObject] The key to look up.
  # @return [Array(BasicObject, BasicObject), nil] A two-element `[key, value]` array, or nil if the key is absent.
  def assoc(key)
    value = fetch(key) { return nil }
    [key, value]
  end

  # (see #compare_keys_by_identity?)
  def compare_by_identity? = compare_keys_by_identity?

  # Implements Ruby's [dig interface](https://docs.ruby-lang.org/en/master/language/dig_methods_rdoc.html).
  # @param key [BasicObject] The key to look up.
  # @param rest [Array<BasicObject>] Additional keys to look up in nested maps.
  # @return [BasicObject, nil] The value found at the nested location, or nil if any key is absent or nil.
  def dig(key, *rest)
    value = self[key]
    return value if rest.empty? || value.nil?
    value.dig(*rest)
  end

  # Returns whether the map contains no entries.
  # @return [Boolean] Whether the map is empty.
  def empty? = size.zero?

  # Return the number of entries currently in the map.
  # @return [Integer]
  def length = size

  # Return whether an observed value matches using this map's value comparison setting.
  # Values are unwrapped before comparison. Concurrent changes may make the result stale.
  # @param value [BasicObject] the value to find
  # @return [Boolean]
  def value?(value)
    identity = compare_values_by_identity?
    each_value.any? { |stored| identity ? stored.equal?(value) : stored == value }
  end
  alias has_value? value?

  # Return a matching key using this map's value comparison setting, or nil.
  # The first observed match is returned. No insertion order is guaranteed.
  # @param value [BasicObject] the value to find
  # @return [BasicObject, nil]
  def key(value)
    pair = rassoc(value)
    pair&.first
  end

  # Return an observed key/value pair using this map's value comparison setting, or nil.
  # Values are unwrapped before comparison. Concurrent changes may make the result stale.
  # @param value [BasicObject] the value to find
  # @return [Array, nil]
  def rassoc(value)
    identity = compare_values_by_identity?
    each_pair do |key, stored|
      return [key, stored] if identity ? stored.equal?(value) : stored == value
    end
    nil
  end

  # Alias for {#key?}
  def has_key?(...) = key?(...) # rubocop:disable Naming/PredicatePrefix
  alias member?  has_key?
  alias include? has_key?

  # Fetches the values associated with multiple keys, using the same missing-key behavior as Hash#fetch.
  # @yield [key] Called for each missing key.
  # @yieldparam key [BasicObject] The missing key.
  # @yieldreturn [BasicObject] The value to return for the missing key.
  # @param keys [Array<BasicObject>] The keys to look up.
  # @return [Array<BasicObject>] An array of the associated values.
  def fetch_values(*keys, &) = keys.map { fetch(it, &) }

  # @note
  #   Some maps may still accept non-shareable keys or values, but convert them into shareable representations.
  #   This method will still return `true` for such maps.
  #
  # @return [Boolean] Whether the map requires keys to be Ractor-shareable
  def shareable_keys? = false

  # @return [Boolean] Whether the map requires values to be Ractor-shareable
  def shareable_values? = false

  # Creates a new Array containing the map's key-value pairs as two-element arrays.
  # @return [Array<Array(BasicObject, BasicObject)>>] A new Array of `[key, value]` arrays.
  def to_a = each_pair.to_a

  # Creates a new Hash containing the map's entries.
  # Preserves identity comparison for keys, including when a block transforms entries.
  # @yieldparam key [BasicObject] an existing key
  # @yieldparam value [BasicObject] its value
  # @yieldreturn [Array(BasicObject, BasicObject)] the key and value for the new Hash
  # @return [Hash] A new Hash with the original entries, or the pairs returned by the block.
  def to_h(&) = entries_to_hash(each_pair, &)

  # Support implicit Hash conversion using this map's {#to_h} implementation.
  # @return [Hash] A new Hash containing the map's entries.
  def to_hash = to_h

  # Support hash patterns using the same entries and key comparison as {#to_h}.
  # Like Hash, this returns all entries regardless of the requested keys.
  # @param keys [Array, nil] the optional key hint supplied by Ruby's pattern matcher
  # @return [Hash] A new Hash containing the map's entries.
  def deconstruct_keys(keys) = to_h # rubocop:disable Lint/UnusedMethodArgument

  # Fetches the values associated with multiple keys, returning nil for any missing keys.
  # @param keys [Array<BasicObject>] The keys to look up.
  # @return [Array<BasicObject>] An array of the associated values, with nil for any missing keys.
  def values_at(*keys) = keys.map { self[it] }

  # Some maps reference their keys weakly, automatically dropping entries when a key gets garbage-collected.
  # @return [Boolean] Whether the map uses weak references for keys.
  def weak_keys? = false

  # Some maps reference their values weakly, automatically dropping entries when a value gets garbage-collected.
  # @return [Boolean] Whether the map uses weak references for values.
  def weak_values? = false

  # @return [String] String representation of the map, suitable for debugging.
  def to_s = inspect

  # @api private
  def inspect_with(inspector)
    super do
      yield if block_given?
      inspector.breakable
      inspector.group("{", "}") do
        inspector.breakable ""
        inspector.seplist(self, nil, :each_for_inspect) do |key, value|
          inspector.group { inspect_pair(inspector, key, value) }
        end
      end
    end
  end

  protected

  # Convert a public value to its stored representation.
  # @api private
  def wrap_value(value) = value

  # Convert a stored representation to its public value.
  # @api private
  def unwrap_value(value) = value

  private

  def entries_to_hash(entries, &)
    return entries.to_h(&) unless compare_keys_by_identity?
    hash = {}.compare_by_identity
    entries.each do |key, value|
      if block_given?
        pair = Array.try_convert(yield(key, value))
        raise TypeError, "block must return an Array or respond to #to_ary" unless pair
        raise ArgumentError, "block must return a two-element pair" unless pair.size == 2
        key, value = pair
      end
      hash[key] = value
    end
    hash
  end

  def convert_entries(entries)
    return entries if Map === entries
    if entries.respond_to?(:to_hash)
      entries = Hash.try_convert(entries)
      raise TypeError, "entries must be a Hash or respond to #to_hash" unless entries
    end
    return entries if entries.nil? || entries.respond_to?(:each)
    raise TypeError, "entries must yield key/value pairs with #each"
  end

  def each_for_inspect(&)                 = each(&)
  def inspect_pair(inspector, key, value) = inspector.hash_pair(key, value) { inspect_value(inspector, value) }
  def inspect_value(inspector, ...)       = inspector.object(...)
end

#as_extended_json(**options) ⇒ Hash

Note:

This method is only available if BSON has been loaded.

Represent current entries as Extended JSON, forwarding BSON's format options.

Parameters:

  • options (Hash) —

    Options forwarded to Hash#as_extended_json.

Returns:

  • (Hash) —

    The Extended JSON representation.



59
# File 'lib/farce/integrations/bson.rb', line 59

def as_extended_json(**) = to_h.as_extended_json(**)

#as_json ⇒ Hash

Note:

This methods is only available if ActiveSupport has been loaded.

Convert entries using ActiveSupport's Hash JSON conversion.

Returns:

  • (Hash) —

    The entries converted using Hash#as_json.



14
# File 'lib/farce/integrations/active_support/map.rb', line 14

def as_json(...) = to_h.as_json(...)

#assert_valid_keys(*valid_keys) ⇒ self

Note:

This methods is only available if ActiveSupport has been loaded.

Validate observed keys without normalizing the allowed keys. Concurrent changes may invalidate the result immediately.

Returns:

  • (self)

Raises:

  • (ArgumentError) —

    if an observed key is not allowed



27
28
29
30
31
32
33
34
35
# File 'lib/farce/integrations/active_support/map.rb', line 27

def assert_valid_keys(*valid_keys)
  valid_keys.flatten!
  each_key do |key|
    unless valid_keys.include?(key)
      raise ArgumentError, "Unknown key: #{key.inspect}. Valid keys are: #{valid_keys.map(&:inspect).join(", ")}"
    end
  end
  self
end

#assoc(key) ⇒ Array(BasicObject, BasicObject)?

Return a two-element array containing a key and its associated value, if the key is present, or nil if the key is absent.

Parameters:

  • key (BasicObject) —

    The key to look up.

Returns:

  • (Array(BasicObject, BasicObject), nil) —

    A two-element [key, value] array, or nil if the key is absent.



171
172
173
174
# File 'lib/farce/abstract/map.rb', line 171

def assoc(key)
  value = fetch(key) { return nil }
  [key, value]
end

#bson_type ⇒ String

Note:

This method is only available if BSON has been loaded.

Identify this value as a BSON document when embedded in a document or array.

Returns:

  • (String) —

    The BSON document type byte.



47
# File 'lib/farce/integrations/bson.rb', line 47

def bson_type = ::BSON::Hash::BSON_TYPE

#clear ⇒ self

This method is abstract.

Remove all entries from the map.

Returns:

  • (self)


155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
# File 'lib/farce/abstract/map.rb', line 155

class Map
  include Internal::MarshalSupport::Map
  include Enumerable
  include Internal::Inspect

  # Store a value using the map's assignment operation.
  # Concurrent maps override this method to support timeouts.
  # @param key [BasicObject] the key to store
  # @param value [BasicObject] the value to store
  # @return [BasicObject] `value`
  def store(key, value) = self[key] = value

  # Return a two-element array containing a key and its associated value, if the key is present,
  # or nil if the key is absent.
  # @param key [BasicObject] The key to look up.
  # @return [Array(BasicObject, BasicObject), nil] A two-element `[key, value]` array, or nil if the key is absent.
  def assoc(key)
    value = fetch(key) { return nil }
    [key, value]
  end

  # (see #compare_keys_by_identity?)
  def compare_by_identity? = compare_keys_by_identity?

  # Implements Ruby's [dig interface](https://docs.ruby-lang.org/en/master/language/dig_methods_rdoc.html).
  # @param key [BasicObject] The key to look up.
  # @param rest [Array<BasicObject>] Additional keys to look up in nested maps.
  # @return [BasicObject, nil] The value found at the nested location, or nil if any key is absent or nil.
  def dig(key, *rest)
    value = self[key]
    return value if rest.empty? || value.nil?
    value.dig(*rest)
  end

  # Returns whether the map contains no entries.
  # @return [Boolean] Whether the map is empty.
  def empty? = size.zero?

  # Return the number of entries currently in the map.
  # @return [Integer]
  def length = size

  # Return whether an observed value matches using this map's value comparison setting.
  # Values are unwrapped before comparison. Concurrent changes may make the result stale.
  # @param value [BasicObject] the value to find
  # @return [Boolean]
  def value?(value)
    identity = compare_values_by_identity?
    each_value.any? { |stored| identity ? stored.equal?(value) : stored == value }
  end
  alias has_value? value?

  # Return a matching key using this map's value comparison setting, or nil.
  # The first observed match is returned. No insertion order is guaranteed.
  # @param value [BasicObject] the value to find
  # @return [BasicObject, nil]
  def key(value)
    pair = rassoc(value)
    pair&.first
  end

  # Return an observed key/value pair using this map's value comparison setting, or nil.
  # Values are unwrapped before comparison. Concurrent changes may make the result stale.
  # @param value [BasicObject] the value to find
  # @return [Array, nil]
  def rassoc(value)
    identity = compare_values_by_identity?
    each_pair do |key, stored|
      return [key, stored] if identity ? stored.equal?(value) : stored == value
    end
    nil
  end

  # Alias for {#key?}
  def has_key?(...) = key?(...) # rubocop:disable Naming/PredicatePrefix
  alias member?  has_key?
  alias include? has_key?

  # Fetches the values associated with multiple keys, using the same missing-key behavior as Hash#fetch.
  # @yield [key] Called for each missing key.
  # @yieldparam key [BasicObject] The missing key.
  # @yieldreturn [BasicObject] The value to return for the missing key.
  # @param keys [Array<BasicObject>] The keys to look up.
  # @return [Array<BasicObject>] An array of the associated values.
  def fetch_values(*keys, &) = keys.map { fetch(it, &) }

  # @note
  #   Some maps may still accept non-shareable keys or values, but convert them into shareable representations.
  #   This method will still return `true` for such maps.
  #
  # @return [Boolean] Whether the map requires keys to be Ractor-shareable
  def shareable_keys? = false

  # @return [Boolean] Whether the map requires values to be Ractor-shareable
  def shareable_values? = false

  # Creates a new Array containing the map's key-value pairs as two-element arrays.
  # @return [Array<Array(BasicObject, BasicObject)>>] A new Array of `[key, value]` arrays.
  def to_a = each_pair.to_a

  # Creates a new Hash containing the map's entries.
  # Preserves identity comparison for keys, including when a block transforms entries.
  # @yieldparam key [BasicObject] an existing key
  # @yieldparam value [BasicObject] its value
  # @yieldreturn [Array(BasicObject, BasicObject)] the key and value for the new Hash
  # @return [Hash] A new Hash with the original entries, or the pairs returned by the block.
  def to_h(&) = entries_to_hash(each_pair, &)

  # Support implicit Hash conversion using this map's {#to_h} implementation.
  # @return [Hash] A new Hash containing the map's entries.
  def to_hash = to_h

  # Support hash patterns using the same entries and key comparison as {#to_h}.
  # Like Hash, this returns all entries regardless of the requested keys.
  # @param keys [Array, nil] the optional key hint supplied by Ruby's pattern matcher
  # @return [Hash] A new Hash containing the map's entries.
  def deconstruct_keys(keys) = to_h # rubocop:disable Lint/UnusedMethodArgument

  # Fetches the values associated with multiple keys, returning nil for any missing keys.
  # @param keys [Array<BasicObject>] The keys to look up.
  # @return [Array<BasicObject>] An array of the associated values, with nil for any missing keys.
  def values_at(*keys) = keys.map { self[it] }

  # Some maps reference their keys weakly, automatically dropping entries when a key gets garbage-collected.
  # @return [Boolean] Whether the map uses weak references for keys.
  def weak_keys? = false

  # Some maps reference their values weakly, automatically dropping entries when a value gets garbage-collected.
  # @return [Boolean] Whether the map uses weak references for values.
  def weak_values? = false

  # @return [String] String representation of the map, suitable for debugging.
  def to_s = inspect

  # @api private
  def inspect_with(inspector)
    super do
      yield if block_given?
      inspector.breakable
      inspector.group("{", "}") do
        inspector.breakable ""
        inspector.seplist(self, nil, :each_for_inspect) do |key, value|
          inspector.group { inspect_pair(inspector, key, value) }
        end
      end
    end
  end

  protected

  # Convert a public value to its stored representation.
  # @api private
  def wrap_value(value) = value

  # Convert a stored representation to its public value.
  # @api private
  def unwrap_value(value) = value

  private

  def entries_to_hash(entries, &)
    return entries.to_h(&) unless compare_keys_by_identity?
    hash = {}.compare_by_identity
    entries.each do |key, value|
      if block_given?
        pair = Array.try_convert(yield(key, value))
        raise TypeError, "block must return an Array or respond to #to_ary" unless pair
        raise ArgumentError, "block must return a two-element pair" unless pair.size == 2
        key, value = pair
      end
      hash[key] = value
    end
    hash
  end

  def convert_entries(entries)
    return entries if Map === entries
    if entries.respond_to?(:to_hash)
      entries = Hash.try_convert(entries)
      raise TypeError, "entries must be a Hash or respond to #to_hash" unless entries
    end
    return entries if entries.nil? || entries.respond_to?(:each)
    raise TypeError, "entries must yield key/value pairs with #each"
  end

  def each_for_inspect(&)                 = each(&)
  def inspect_pair(inspector, key, value) = inspector.hash_pair(key, value) { inspect_value(inspector, value) }
  def inspect_value(inspector, ...)       = inspector.object(...)
end

#compare_by_identity? ⇒ Boolean

This method is abstract.

Returns Whether keys are compared by identity instead of hash and eql?.

Returns:

  • (Boolean) —

    Whether keys are compared by identity instead of hash and eql?.



177
# File 'lib/farce/abstract/map.rb', line 177

def compare_by_identity? = compare_keys_by_identity?

#compare_keys_by_identity? ⇒ Boolean

This method is abstract.

Returns Whether keys are compared by identity instead of hash and eql?.

Returns:

  • (Boolean) —

    Whether keys are compared by identity instead of hash and eql?.



155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
# File 'lib/farce/abstract/map.rb', line 155

class Map
  include Internal::MarshalSupport::Map
  include Enumerable
  include Internal::Inspect

  # Store a value using the map's assignment operation.
  # Concurrent maps override this method to support timeouts.
  # @param key [BasicObject] the key to store
  # @param value [BasicObject] the value to store
  # @return [BasicObject] `value`
  def store(key, value) = self[key] = value

  # Return a two-element array containing a key and its associated value, if the key is present,
  # or nil if the key is absent.
  # @param key [BasicObject] The key to look up.
  # @return [Array(BasicObject, BasicObject), nil] A two-element `[key, value]` array, or nil if the key is absent.
  def assoc(key)
    value = fetch(key) { return nil }
    [key, value]
  end

  # (see #compare_keys_by_identity?)
  def compare_by_identity? = compare_keys_by_identity?

  # Implements Ruby's [dig interface](https://docs.ruby-lang.org/en/master/language/dig_methods_rdoc.html).
  # @param key [BasicObject] The key to look up.
  # @param rest [Array<BasicObject>] Additional keys to look up in nested maps.
  # @return [BasicObject, nil] The value found at the nested location, or nil if any key is absent or nil.
  def dig(key, *rest)
    value = self[key]
    return value if rest.empty? || value.nil?
    value.dig(*rest)
  end

  # Returns whether the map contains no entries.
  # @return [Boolean] Whether the map is empty.
  def empty? = size.zero?

  # Return the number of entries currently in the map.
  # @return [Integer]
  def length = size

  # Return whether an observed value matches using this map's value comparison setting.
  # Values are unwrapped before comparison. Concurrent changes may make the result stale.
  # @param value [BasicObject] the value to find
  # @return [Boolean]
  def value?(value)
    identity = compare_values_by_identity?
    each_value.any? { |stored| identity ? stored.equal?(value) : stored == value }
  end
  alias has_value? value?

  # Return a matching key using this map's value comparison setting, or nil.
  # The first observed match is returned. No insertion order is guaranteed.
  # @param value [BasicObject] the value to find
  # @return [BasicObject, nil]
  def key(value)
    pair = rassoc(value)
    pair&.first
  end

  # Return an observed key/value pair using this map's value comparison setting, or nil.
  # Values are unwrapped before comparison. Concurrent changes may make the result stale.
  # @param value [BasicObject] the value to find
  # @return [Array, nil]
  def rassoc(value)
    identity = compare_values_by_identity?
    each_pair do |key, stored|
      return [key, stored] if identity ? stored.equal?(value) : stored == value
    end
    nil
  end

  # Alias for {#key?}
  def has_key?(...) = key?(...) # rubocop:disable Naming/PredicatePrefix
  alias member?  has_key?
  alias include? has_key?

  # Fetches the values associated with multiple keys, using the same missing-key behavior as Hash#fetch.
  # @yield [key] Called for each missing key.
  # @yieldparam key [BasicObject] The missing key.
  # @yieldreturn [BasicObject] The value to return for the missing key.
  # @param keys [Array<BasicObject>] The keys to look up.
  # @return [Array<BasicObject>] An array of the associated values.
  def fetch_values(*keys, &) = keys.map { fetch(it, &) }

  # @note
  #   Some maps may still accept non-shareable keys or values, but convert them into shareable representations.
  #   This method will still return `true` for such maps.
  #
  # @return [Boolean] Whether the map requires keys to be Ractor-shareable
  def shareable_keys? = false

  # @return [Boolean] Whether the map requires values to be Ractor-shareable
  def shareable_values? = false

  # Creates a new Array containing the map's key-value pairs as two-element arrays.
  # @return [Array<Array(BasicObject, BasicObject)>>] A new Array of `[key, value]` arrays.
  def to_a = each_pair.to_a

  # Creates a new Hash containing the map's entries.
  # Preserves identity comparison for keys, including when a block transforms entries.
  # @yieldparam key [BasicObject] an existing key
  # @yieldparam value [BasicObject] its value
  # @yieldreturn [Array(BasicObject, BasicObject)] the key and value for the new Hash
  # @return [Hash] A new Hash with the original entries, or the pairs returned by the block.
  def to_h(&) = entries_to_hash(each_pair, &)

  # Support implicit Hash conversion using this map's {#to_h} implementation.
  # @return [Hash] A new Hash containing the map's entries.
  def to_hash = to_h

  # Support hash patterns using the same entries and key comparison as {#to_h}.
  # Like Hash, this returns all entries regardless of the requested keys.
  # @param keys [Array, nil] the optional key hint supplied by Ruby's pattern matcher
  # @return [Hash] A new Hash containing the map's entries.
  def deconstruct_keys(keys) = to_h # rubocop:disable Lint/UnusedMethodArgument

  # Fetches the values associated with multiple keys, returning nil for any missing keys.
  # @param keys [Array<BasicObject>] The keys to look up.
  # @return [Array<BasicObject>] An array of the associated values, with nil for any missing keys.
  def values_at(*keys) = keys.map { self[it] }

  # Some maps reference their keys weakly, automatically dropping entries when a key gets garbage-collected.
  # @return [Boolean] Whether the map uses weak references for keys.
  def weak_keys? = false

  # Some maps reference their values weakly, automatically dropping entries when a value gets garbage-collected.
  # @return [Boolean] Whether the map uses weak references for values.
  def weak_values? = false

  # @return [String] String representation of the map, suitable for debugging.
  def to_s = inspect

  # @api private
  def inspect_with(inspector)
    super do
      yield if block_given?
      inspector.breakable
      inspector.group("{", "}") do
        inspector.breakable ""
        inspector.seplist(self, nil, :each_for_inspect) do |key, value|
          inspector.group { inspect_pair(inspector, key, value) }
        end
      end
    end
  end

  protected

  # Convert a public value to its stored representation.
  # @api private
  def wrap_value(value) = value

  # Convert a stored representation to its public value.
  # @api private
  def unwrap_value(value) = value

  private

  def entries_to_hash(entries, &)
    return entries.to_h(&) unless compare_keys_by_identity?
    hash = {}.compare_by_identity
    entries.each do |key, value|
      if block_given?
        pair = Array.try_convert(yield(key, value))
        raise TypeError, "block must return an Array or respond to #to_ary" unless pair
        raise ArgumentError, "block must return a two-element pair" unless pair.size == 2
        key, value = pair
      end
      hash[key] = value
    end
    hash
  end

  def convert_entries(entries)
    return entries if Map === entries
    if entries.respond_to?(:to_hash)
      entries = Hash.try_convert(entries)
      raise TypeError, "entries must be a Hash or respond to #to_hash" unless entries
    end
    return entries if entries.nil? || entries.respond_to?(:each)
    raise TypeError, "entries must yield key/value pairs with #each"
  end

  def each_for_inspect(&)                 = each(&)
  def inspect_pair(inspector, key, value) = inspector.hash_pair(key, value) { inspect_value(inspector, value) }
  def inspect_value(inspector, ...)       = inspector.object(...)
end

#compare_values_by_identity? ⇒ Boolean

This method is abstract.

Returns Whether values are compared by identity instead of equality.

Returns:

  • (Boolean) —

    Whether values are compared by identity instead of equality.



155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
# File 'lib/farce/abstract/map.rb', line 155

class Map
  include Internal::MarshalSupport::Map
  include Enumerable
  include Internal::Inspect

  # Store a value using the map's assignment operation.
  # Concurrent maps override this method to support timeouts.
  # @param key [BasicObject] the key to store
  # @param value [BasicObject] the value to store
  # @return [BasicObject] `value`
  def store(key, value) = self[key] = value

  # Return a two-element array containing a key and its associated value, if the key is present,
  # or nil if the key is absent.
  # @param key [BasicObject] The key to look up.
  # @return [Array(BasicObject, BasicObject), nil] A two-element `[key, value]` array, or nil if the key is absent.
  def assoc(key)
    value = fetch(key) { return nil }
    [key, value]
  end

  # (see #compare_keys_by_identity?)
  def compare_by_identity? = compare_keys_by_identity?

  # Implements Ruby's [dig interface](https://docs.ruby-lang.org/en/master/language/dig_methods_rdoc.html).
  # @param key [BasicObject] The key to look up.
  # @param rest [Array<BasicObject>] Additional keys to look up in nested maps.
  # @return [BasicObject, nil] The value found at the nested location, or nil if any key is absent or nil.
  def dig(key, *rest)
    value = self[key]
    return value if rest.empty? || value.nil?
    value.dig(*rest)
  end

  # Returns whether the map contains no entries.
  # @return [Boolean] Whether the map is empty.
  def empty? = size.zero?

  # Return the number of entries currently in the map.
  # @return [Integer]
  def length = size

  # Return whether an observed value matches using this map's value comparison setting.
  # Values are unwrapped before comparison. Concurrent changes may make the result stale.
  # @param value [BasicObject] the value to find
  # @return [Boolean]
  def value?(value)
    identity = compare_values_by_identity?
    each_value.any? { |stored| identity ? stored.equal?(value) : stored == value }
  end
  alias has_value? value?

  # Return a matching key using this map's value comparison setting, or nil.
  # The first observed match is returned. No insertion order is guaranteed.
  # @param value [BasicObject] the value to find
  # @return [BasicObject, nil]
  def key(value)
    pair = rassoc(value)
    pair&.first
  end

  # Return an observed key/value pair using this map's value comparison setting, or nil.
  # Values are unwrapped before comparison. Concurrent changes may make the result stale.
  # @param value [BasicObject] the value to find
  # @return [Array, nil]
  def rassoc(value)
    identity = compare_values_by_identity?
    each_pair do |key, stored|
      return [key, stored] if identity ? stored.equal?(value) : stored == value
    end
    nil
  end

  # Alias for {#key?}
  def has_key?(...) = key?(...) # rubocop:disable Naming/PredicatePrefix
  alias member?  has_key?
  alias include? has_key?

  # Fetches the values associated with multiple keys, using the same missing-key behavior as Hash#fetch.
  # @yield [key] Called for each missing key.
  # @yieldparam key [BasicObject] The missing key.
  # @yieldreturn [BasicObject] The value to return for the missing key.
  # @param keys [Array<BasicObject>] The keys to look up.
  # @return [Array<BasicObject>] An array of the associated values.
  def fetch_values(*keys, &) = keys.map { fetch(it, &) }

  # @note
  #   Some maps may still accept non-shareable keys or values, but convert them into shareable representations.
  #   This method will still return `true` for such maps.
  #
  # @return [Boolean] Whether the map requires keys to be Ractor-shareable
  def shareable_keys? = false

  # @return [Boolean] Whether the map requires values to be Ractor-shareable
  def shareable_values? = false

  # Creates a new Array containing the map's key-value pairs as two-element arrays.
  # @return [Array<Array(BasicObject, BasicObject)>>] A new Array of `[key, value]` arrays.
  def to_a = each_pair.to_a

  # Creates a new Hash containing the map's entries.
  # Preserves identity comparison for keys, including when a block transforms entries.
  # @yieldparam key [BasicObject] an existing key
  # @yieldparam value [BasicObject] its value
  # @yieldreturn [Array(BasicObject, BasicObject)] the key and value for the new Hash
  # @return [Hash] A new Hash with the original entries, or the pairs returned by the block.
  def to_h(&) = entries_to_hash(each_pair, &)

  # Support implicit Hash conversion using this map's {#to_h} implementation.
  # @return [Hash] A new Hash containing the map's entries.
  def to_hash = to_h

  # Support hash patterns using the same entries and key comparison as {#to_h}.
  # Like Hash, this returns all entries regardless of the requested keys.
  # @param keys [Array, nil] the optional key hint supplied by Ruby's pattern matcher
  # @return [Hash] A new Hash containing the map's entries.
  def deconstruct_keys(keys) = to_h # rubocop:disable Lint/UnusedMethodArgument

  # Fetches the values associated with multiple keys, returning nil for any missing keys.
  # @param keys [Array<BasicObject>] The keys to look up.
  # @return [Array<BasicObject>] An array of the associated values, with nil for any missing keys.
  def values_at(*keys) = keys.map { self[it] }

  # Some maps reference their keys weakly, automatically dropping entries when a key gets garbage-collected.
  # @return [Boolean] Whether the map uses weak references for keys.
  def weak_keys? = false

  # Some maps reference their values weakly, automatically dropping entries when a value gets garbage-collected.
  # @return [Boolean] Whether the map uses weak references for values.
  def weak_values? = false

  # @return [String] String representation of the map, suitable for debugging.
  def to_s = inspect

  # @api private
  def inspect_with(inspector)
    super do
      yield if block_given?
      inspector.breakable
      inspector.group("{", "}") do
        inspector.breakable ""
        inspector.seplist(self, nil, :each_for_inspect) do |key, value|
          inspector.group { inspect_pair(inspector, key, value) }
        end
      end
    end
  end

  protected

  # Convert a public value to its stored representation.
  # @api private
  def wrap_value(value) = value

  # Convert a stored representation to its public value.
  # @api private
  def unwrap_value(value) = value

  private

  def entries_to_hash(entries, &)
    return entries.to_h(&) unless compare_keys_by_identity?
    hash = {}.compare_by_identity
    entries.each do |key, value|
      if block_given?
        pair = Array.try_convert(yield(key, value))
        raise TypeError, "block must return an Array or respond to #to_ary" unless pair
        raise ArgumentError, "block must return a two-element pair" unless pair.size == 2
        key, value = pair
      end
      hash[key] = value
    end
    hash
  end

  def convert_entries(entries)
    return entries if Map === entries
    if entries.respond_to?(:to_hash)
      entries = Hash.try_convert(entries)
      raise TypeError, "entries must be a Hash or respond to #to_hash" unless entries
    end
    return entries if entries.nil? || entries.respond_to?(:each)
    raise TypeError, "entries must yield key/value pairs with #each"
  end

  def each_for_inspect(&)                 = each(&)
  def inspect_pair(inspector, key, value) = inspector.hash_pair(key, value) { inspect_value(inspector, value) }
  def inspect_value(inspector, ...)       = inspector.object(...)
end

#deconstruct_keys(keys) ⇒ Hash

Support hash patterns using the same entries and key comparison as #to_h. Like Hash, this returns all entries regardless of the requested keys.

Parameters:

  • keys (Array, nil) —

    the optional key hint supplied by Ruby's pattern matcher

Returns:

  • (Hash) —

    A new Hash containing the map's entries.



271
# File 'lib/farce/abstract/map.rb', line 271

def deconstruct_keys(keys) = to_h # rubocop:disable Lint/UnusedMethodArgument

#delete(key) ⇒ BasicObject?

This method is abstract.

Remove a key and its associated value.

Parameters:

  • key (BasicObject) —

    The key to remove.

Returns:

  • (BasicObject, nil) —

    The removed value, or nil if the key was absent.



155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
# File 'lib/farce/abstract/map.rb', line 155

class Map
  include Internal::MarshalSupport::Map
  include Enumerable
  include Internal::Inspect

  # Store a value using the map's assignment operation.
  # Concurrent maps override this method to support timeouts.
  # @param key [BasicObject] the key to store
  # @param value [BasicObject] the value to store
  # @return [BasicObject] `value`
  def store(key, value) = self[key] = value

  # Return a two-element array containing a key and its associated value, if the key is present,
  # or nil if the key is absent.
  # @param key [BasicObject] The key to look up.
  # @return [Array(BasicObject, BasicObject), nil] A two-element `[key, value]` array, or nil if the key is absent.
  def assoc(key)
    value = fetch(key) { return nil }
    [key, value]
  end

  # (see #compare_keys_by_identity?)
  def compare_by_identity? = compare_keys_by_identity?

  # Implements Ruby's [dig interface](https://docs.ruby-lang.org/en/master/language/dig_methods_rdoc.html).
  # @param key [BasicObject] The key to look up.
  # @param rest [Array<BasicObject>] Additional keys to look up in nested maps.
  # @return [BasicObject, nil] The value found at the nested location, or nil if any key is absent or nil.
  def dig(key, *rest)
    value = self[key]
    return value if rest.empty? || value.nil?
    value.dig(*rest)
  end

  # Returns whether the map contains no entries.
  # @return [Boolean] Whether the map is empty.
  def empty? = size.zero?

  # Return the number of entries currently in the map.
  # @return [Integer]
  def length = size

  # Return whether an observed value matches using this map's value comparison setting.
  # Values are unwrapped before comparison. Concurrent changes may make the result stale.
  # @param value [BasicObject] the value to find
  # @return [Boolean]
  def value?(value)
    identity = compare_values_by_identity?
    each_value.any? { |stored| identity ? stored.equal?(value) : stored == value }
  end
  alias has_value? value?

  # Return a matching key using this map's value comparison setting, or nil.
  # The first observed match is returned. No insertion order is guaranteed.
  # @param value [BasicObject] the value to find
  # @return [BasicObject, nil]
  def key(value)
    pair = rassoc(value)
    pair&.first
  end

  # Return an observed key/value pair using this map's value comparison setting, or nil.
  # Values are unwrapped before comparison. Concurrent changes may make the result stale.
  # @param value [BasicObject] the value to find
  # @return [Array, nil]
  def rassoc(value)
    identity = compare_values_by_identity?
    each_pair do |key, stored|
      return [key, stored] if identity ? stored.equal?(value) : stored == value
    end
    nil
  end

  # Alias for {#key?}
  def has_key?(...) = key?(...) # rubocop:disable Naming/PredicatePrefix
  alias member?  has_key?
  alias include? has_key?

  # Fetches the values associated with multiple keys, using the same missing-key behavior as Hash#fetch.
  # @yield [key] Called for each missing key.
  # @yieldparam key [BasicObject] The missing key.
  # @yieldreturn [BasicObject] The value to return for the missing key.
  # @param keys [Array<BasicObject>] The keys to look up.
  # @return [Array<BasicObject>] An array of the associated values.
  def fetch_values(*keys, &) = keys.map { fetch(it, &) }

  # @note
  #   Some maps may still accept non-shareable keys or values, but convert them into shareable representations.
  #   This method will still return `true` for such maps.
  #
  # @return [Boolean] Whether the map requires keys to be Ractor-shareable
  def shareable_keys? = false

  # @return [Boolean] Whether the map requires values to be Ractor-shareable
  def shareable_values? = false

  # Creates a new Array containing the map's key-value pairs as two-element arrays.
  # @return [Array<Array(BasicObject, BasicObject)>>] A new Array of `[key, value]` arrays.
  def to_a = each_pair.to_a

  # Creates a new Hash containing the map's entries.
  # Preserves identity comparison for keys, including when a block transforms entries.
  # @yieldparam key [BasicObject] an existing key
  # @yieldparam value [BasicObject] its value
  # @yieldreturn [Array(BasicObject, BasicObject)] the key and value for the new Hash
  # @return [Hash] A new Hash with the original entries, or the pairs returned by the block.
  def to_h(&) = entries_to_hash(each_pair, &)

  # Support implicit Hash conversion using this map's {#to_h} implementation.
  # @return [Hash] A new Hash containing the map's entries.
  def to_hash = to_h

  # Support hash patterns using the same entries and key comparison as {#to_h}.
  # Like Hash, this returns all entries regardless of the requested keys.
  # @param keys [Array, nil] the optional key hint supplied by Ruby's pattern matcher
  # @return [Hash] A new Hash containing the map's entries.
  def deconstruct_keys(keys) = to_h # rubocop:disable Lint/UnusedMethodArgument

  # Fetches the values associated with multiple keys, returning nil for any missing keys.
  # @param keys [Array<BasicObject>] The keys to look up.
  # @return [Array<BasicObject>] An array of the associated values, with nil for any missing keys.
  def values_at(*keys) = keys.map { self[it] }

  # Some maps reference their keys weakly, automatically dropping entries when a key gets garbage-collected.
  # @return [Boolean] Whether the map uses weak references for keys.
  def weak_keys? = false

  # Some maps reference their values weakly, automatically dropping entries when a value gets garbage-collected.
  # @return [Boolean] Whether the map uses weak references for values.
  def weak_values? = false

  # @return [String] String representation of the map, suitable for debugging.
  def to_s = inspect

  # @api private
  def inspect_with(inspector)
    super do
      yield if block_given?
      inspector.breakable
      inspector.group("{", "}") do
        inspector.breakable ""
        inspector.seplist(self, nil, :each_for_inspect) do |key, value|
          inspector.group { inspect_pair(inspector, key, value) }
        end
      end
    end
  end

  protected

  # Convert a public value to its stored representation.
  # @api private
  def wrap_value(value) = value

  # Convert a stored representation to its public value.
  # @api private
  def unwrap_value(value) = value

  private

  def entries_to_hash(entries, &)
    return entries.to_h(&) unless compare_keys_by_identity?
    hash = {}.compare_by_identity
    entries.each do |key, value|
      if block_given?
        pair = Array.try_convert(yield(key, value))
        raise TypeError, "block must return an Array or respond to #to_ary" unless pair
        raise ArgumentError, "block must return a two-element pair" unless pair.size == 2
        key, value = pair
      end
      hash[key] = value
    end
    hash
  end

  def convert_entries(entries)
    return entries if Map === entries
    if entries.respond_to?(:to_hash)
      entries = Hash.try_convert(entries)
      raise TypeError, "entries must be a Hash or respond to #to_hash" unless entries
    end
    return entries if entries.nil? || entries.respond_to?(:each)
    raise TypeError, "entries must yield key/value pairs with #each"
  end

  def each_for_inspect(&)                 = each(&)
  def inspect_pair(inspector, key, value) = inspector.hash_pair(key, value) { inspect_value(inspector, value) }
  def inspect_value(inspector, ...)       = inspector.object(...)
end

#dig(key, *rest) ⇒ BasicObject?

Implements Ruby's dig interface.

Parameters:

  • key (BasicObject) —

    The key to look up.

  • rest (Array<BasicObject>) —

    Additional keys to look up in nested maps.

Returns:

  • (BasicObject, nil) —

    The value found at the nested location, or nil if any key is absent or nil.



183
184
185
186
187
# File 'lib/farce/abstract/map.rb', line 183

def dig(key, *rest)
  value = self[key]
  return value if rest.empty? || value.nil?
  value.dig(*rest)
end

#each {|pair| ... } ⇒ self #each ⇒ Enumerator

This method is abstract.

Iterate over the map's key-value pairs. Entry consistency and access requirements depend on the implementation. Iteration order is not guaranteed to match insertion order.

Overloads:

  • #each {|pair| ... } ⇒ self

    Yields:

    • (pair) —

      Called once for each entry.

    Yield Parameters:

    • pair (Array<BasicObject>) —

      A two-element [key, value] pair.

    Returns:

    • (self)
  • #each ⇒ Enumerator

    Returns An enumerator over two-element [key, value] pairs.

    Returns:

    • (Enumerator) —

      An enumerator over two-element [key, value] pairs.



155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
# File 'lib/farce/abstract/map.rb', line 155

class Map
  include Internal::MarshalSupport::Map
  include Enumerable
  include Internal::Inspect

  # Store a value using the map's assignment operation.
  # Concurrent maps override this method to support timeouts.
  # @param key [BasicObject] the key to store
  # @param value [BasicObject] the value to store
  # @return [BasicObject] `value`
  def store(key, value) = self[key] = value

  # Return a two-element array containing a key and its associated value, if the key is present,
  # or nil if the key is absent.
  # @param key [BasicObject] The key to look up.
  # @return [Array(BasicObject, BasicObject), nil] A two-element `[key, value]` array, or nil if the key is absent.
  def assoc(key)
    value = fetch(key) { return nil }
    [key, value]
  end

  # (see #compare_keys_by_identity?)
  def compare_by_identity? = compare_keys_by_identity?

  # Implements Ruby's [dig interface](https://docs.ruby-lang.org/en/master/language/dig_methods_rdoc.html).
  # @param key [BasicObject] The key to look up.
  # @param rest [Array<BasicObject>] Additional keys to look up in nested maps.
  # @return [BasicObject, nil] The value found at the nested location, or nil if any key is absent or nil.
  def dig(key, *rest)
    value = self[key]
    return value if rest.empty? || value.nil?
    value.dig(*rest)
  end

  # Returns whether the map contains no entries.
  # @return [Boolean] Whether the map is empty.
  def empty? = size.zero?

  # Return the number of entries currently in the map.
  # @return [Integer]
  def length = size

  # Return whether an observed value matches using this map's value comparison setting.
  # Values are unwrapped before comparison. Concurrent changes may make the result stale.
  # @param value [BasicObject] the value to find
  # @return [Boolean]
  def value?(value)
    identity = compare_values_by_identity?
    each_value.any? { |stored| identity ? stored.equal?(value) : stored == value }
  end
  alias has_value? value?

  # Return a matching key using this map's value comparison setting, or nil.
  # The first observed match is returned. No insertion order is guaranteed.
  # @param value [BasicObject] the value to find
  # @return [BasicObject, nil]
  def key(value)
    pair = rassoc(value)
    pair&.first
  end

  # Return an observed key/value pair using this map's value comparison setting, or nil.
  # Values are unwrapped before comparison. Concurrent changes may make the result stale.
  # @param value [BasicObject] the value to find
  # @return [Array, nil]
  def rassoc(value)
    identity = compare_values_by_identity?
    each_pair do |key, stored|
      return [key, stored] if identity ? stored.equal?(value) : stored == value
    end
    nil
  end

  # Alias for {#key?}
  def has_key?(...) = key?(...) # rubocop:disable Naming/PredicatePrefix
  alias member?  has_key?
  alias include? has_key?

  # Fetches the values associated with multiple keys, using the same missing-key behavior as Hash#fetch.
  # @yield [key] Called for each missing key.
  # @yieldparam key [BasicObject] The missing key.
  # @yieldreturn [BasicObject] The value to return for the missing key.
  # @param keys [Array<BasicObject>] The keys to look up.
  # @return [Array<BasicObject>] An array of the associated values.
  def fetch_values(*keys, &) = keys.map { fetch(it, &) }

  # @note
  #   Some maps may still accept non-shareable keys or values, but convert them into shareable representations.
  #   This method will still return `true` for such maps.
  #
  # @return [Boolean] Whether the map requires keys to be Ractor-shareable
  def shareable_keys? = false

  # @return [Boolean] Whether the map requires values to be Ractor-shareable
  def shareable_values? = false

  # Creates a new Array containing the map's key-value pairs as two-element arrays.
  # @return [Array<Array(BasicObject, BasicObject)>>] A new Array of `[key, value]` arrays.
  def to_a = each_pair.to_a

  # Creates a new Hash containing the map's entries.
  # Preserves identity comparison for keys, including when a block transforms entries.
  # @yieldparam key [BasicObject] an existing key
  # @yieldparam value [BasicObject] its value
  # @yieldreturn [Array(BasicObject, BasicObject)] the key and value for the new Hash
  # @return [Hash] A new Hash with the original entries, or the pairs returned by the block.
  def to_h(&) = entries_to_hash(each_pair, &)

  # Support implicit Hash conversion using this map's {#to_h} implementation.
  # @return [Hash] A new Hash containing the map's entries.
  def to_hash = to_h

  # Support hash patterns using the same entries and key comparison as {#to_h}.
  # Like Hash, this returns all entries regardless of the requested keys.
  # @param keys [Array, nil] the optional key hint supplied by Ruby's pattern matcher
  # @return [Hash] A new Hash containing the map's entries.
  def deconstruct_keys(keys) = to_h # rubocop:disable Lint/UnusedMethodArgument

  # Fetches the values associated with multiple keys, returning nil for any missing keys.
  # @param keys [Array<BasicObject>] The keys to look up.
  # @return [Array<BasicObject>] An array of the associated values, with nil for any missing keys.
  def values_at(*keys) = keys.map { self[it] }

  # Some maps reference their keys weakly, automatically dropping entries when a key gets garbage-collected.
  # @return [Boolean] Whether the map uses weak references for keys.
  def weak_keys? = false

  # Some maps reference their values weakly, automatically dropping entries when a value gets garbage-collected.
  # @return [Boolean] Whether the map uses weak references for values.
  def weak_values? = false

  # @return [String] String representation of the map, suitable for debugging.
  def to_s = inspect

  # @api private
  def inspect_with(inspector)
    super do
      yield if block_given?
      inspector.breakable
      inspector.group("{", "}") do
        inspector.breakable ""
        inspector.seplist(self, nil, :each_for_inspect) do |key, value|
          inspector.group { inspect_pair(inspector, key, value) }
        end
      end
    end
  end

  protected

  # Convert a public value to its stored representation.
  # @api private
  def wrap_value(value) = value

  # Convert a stored representation to its public value.
  # @api private
  def unwrap_value(value) = value

  private

  def entries_to_hash(entries, &)
    return entries.to_h(&) unless compare_keys_by_identity?
    hash = {}.compare_by_identity
    entries.each do |key, value|
      if block_given?
        pair = Array.try_convert(yield(key, value))
        raise TypeError, "block must return an Array or respond to #to_ary" unless pair
        raise ArgumentError, "block must return a two-element pair" unless pair.size == 2
        key, value = pair
      end
      hash[key] = value
    end
    hash
  end

  def convert_entries(entries)
    return entries if Map === entries
    if entries.respond_to?(:to_hash)
      entries = Hash.try_convert(entries)
      raise TypeError, "entries must be a Hash or respond to #to_hash" unless entries
    end
    return entries if entries.nil? || entries.respond_to?(:each)
    raise TypeError, "entries must yield key/value pairs with #each"
  end

  def each_for_inspect(&)                 = each(&)
  def inspect_pair(inspector, key, value) = inspector.hash_pair(key, value) { inspect_value(inspector, value) }
  def inspect_value(inspector, ...)       = inspector.object(...)
end

#each_key {|key| ... } ⇒ self #each_key ⇒ Enumerator

This method is abstract.

Iterate over the keys currently stored in the map. Keys are not guaranteed to be yielded in insertion order.

Overloads:

  • #each_key {|key| ... } ⇒ self

    Yields:

    • (key) —

      Called once for each stored key.

    Yield Parameters:

    • key (BasicObject) —

      A stored key.

    Returns:

    • (self)
  • #each_key ⇒ Enumerator

    Returns An enumerator over the stored keys.

    Returns:

    • (Enumerator) —

      An enumerator over the stored keys.



155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
# File 'lib/farce/abstract/map.rb', line 155

class Map
  include Internal::MarshalSupport::Map
  include Enumerable
  include Internal::Inspect

  # Store a value using the map's assignment operation.
  # Concurrent maps override this method to support timeouts.
  # @param key [BasicObject] the key to store
  # @param value [BasicObject] the value to store
  # @return [BasicObject] `value`
  def store(key, value) = self[key] = value

  # Return a two-element array containing a key and its associated value, if the key is present,
  # or nil if the key is absent.
  # @param key [BasicObject] The key to look up.
  # @return [Array(BasicObject, BasicObject), nil] A two-element `[key, value]` array, or nil if the key is absent.
  def assoc(key)
    value = fetch(key) { return nil }
    [key, value]
  end

  # (see #compare_keys_by_identity?)
  def compare_by_identity? = compare_keys_by_identity?

  # Implements Ruby's [dig interface](https://docs.ruby-lang.org/en/master/language/dig_methods_rdoc.html).
  # @param key [BasicObject] The key to look up.
  # @param rest [Array<BasicObject>] Additional keys to look up in nested maps.
  # @return [BasicObject, nil] The value found at the nested location, or nil if any key is absent or nil.
  def dig(key, *rest)
    value = self[key]
    return value if rest.empty? || value.nil?
    value.dig(*rest)
  end

  # Returns whether the map contains no entries.
  # @return [Boolean] Whether the map is empty.
  def empty? = size.zero?

  # Return the number of entries currently in the map.
  # @return [Integer]
  def length = size

  # Return whether an observed value matches using this map's value comparison setting.
  # Values are unwrapped before comparison. Concurrent changes may make the result stale.
  # @param value [BasicObject] the value to find
  # @return [Boolean]
  def value?(value)
    identity = compare_values_by_identity?
    each_value.any? { |stored| identity ? stored.equal?(value) : stored == value }
  end
  alias has_value? value?

  # Return a matching key using this map's value comparison setting, or nil.
  # The first observed match is returned. No insertion order is guaranteed.
  # @param value [BasicObject] the value to find
  # @return [BasicObject, nil]
  def key(value)
    pair = rassoc(value)
    pair&.first
  end

  # Return an observed key/value pair using this map's value comparison setting, or nil.
  # Values are unwrapped before comparison. Concurrent changes may make the result stale.
  # @param value [BasicObject] the value to find
  # @return [Array, nil]
  def rassoc(value)
    identity = compare_values_by_identity?
    each_pair do |key, stored|
      return [key, stored] if identity ? stored.equal?(value) : stored == value
    end
    nil
  end

  # Alias for {#key?}
  def has_key?(...) = key?(...) # rubocop:disable Naming/PredicatePrefix
  alias member?  has_key?
  alias include? has_key?

  # Fetches the values associated with multiple keys, using the same missing-key behavior as Hash#fetch.
  # @yield [key] Called for each missing key.
  # @yieldparam key [BasicObject] The missing key.
  # @yieldreturn [BasicObject] The value to return for the missing key.
  # @param keys [Array<BasicObject>] The keys to look up.
  # @return [Array<BasicObject>] An array of the associated values.
  def fetch_values(*keys, &) = keys.map { fetch(it, &) }

  # @note
  #   Some maps may still accept non-shareable keys or values, but convert them into shareable representations.
  #   This method will still return `true` for such maps.
  #
  # @return [Boolean] Whether the map requires keys to be Ractor-shareable
  def shareable_keys? = false

  # @return [Boolean] Whether the map requires values to be Ractor-shareable
  def shareable_values? = false

  # Creates a new Array containing the map's key-value pairs as two-element arrays.
  # @return [Array<Array(BasicObject, BasicObject)>>] A new Array of `[key, value]` arrays.
  def to_a = each_pair.to_a

  # Creates a new Hash containing the map's entries.
  # Preserves identity comparison for keys, including when a block transforms entries.
  # @yieldparam key [BasicObject] an existing key
  # @yieldparam value [BasicObject] its value
  # @yieldreturn [Array(BasicObject, BasicObject)] the key and value for the new Hash
  # @return [Hash] A new Hash with the original entries, or the pairs returned by the block.
  def to_h(&) = entries_to_hash(each_pair, &)

  # Support implicit Hash conversion using this map's {#to_h} implementation.
  # @return [Hash] A new Hash containing the map's entries.
  def to_hash = to_h

  # Support hash patterns using the same entries and key comparison as {#to_h}.
  # Like Hash, this returns all entries regardless of the requested keys.
  # @param keys [Array, nil] the optional key hint supplied by Ruby's pattern matcher
  # @return [Hash] A new Hash containing the map's entries.
  def deconstruct_keys(keys) = to_h # rubocop:disable Lint/UnusedMethodArgument

  # Fetches the values associated with multiple keys, returning nil for any missing keys.
  # @param keys [Array<BasicObject>] The keys to look up.
  # @return [Array<BasicObject>] An array of the associated values, with nil for any missing keys.
  def values_at(*keys) = keys.map { self[it] }

  # Some maps reference their keys weakly, automatically dropping entries when a key gets garbage-collected.
  # @return [Boolean] Whether the map uses weak references for keys.
  def weak_keys? = false

  # Some maps reference their values weakly, automatically dropping entries when a value gets garbage-collected.
  # @return [Boolean] Whether the map uses weak references for values.
  def weak_values? = false

  # @return [String] String representation of the map, suitable for debugging.
  def to_s = inspect

  # @api private
  def inspect_with(inspector)
    super do
      yield if block_given?
      inspector.breakable
      inspector.group("{", "}") do
        inspector.breakable ""
        inspector.seplist(self, nil, :each_for_inspect) do |key, value|
          inspector.group { inspect_pair(inspector, key, value) }
        end
      end
    end
  end

  protected

  # Convert a public value to its stored representation.
  # @api private
  def wrap_value(value) = value

  # Convert a stored representation to its public value.
  # @api private
  def unwrap_value(value) = value

  private

  def entries_to_hash(entries, &)
    return entries.to_h(&) unless compare_keys_by_identity?
    hash = {}.compare_by_identity
    entries.each do |key, value|
      if block_given?
        pair = Array.try_convert(yield(key, value))
        raise TypeError, "block must return an Array or respond to #to_ary" unless pair
        raise ArgumentError, "block must return a two-element pair" unless pair.size == 2
        key, value = pair
      end
      hash[key] = value
    end
    hash
  end

  def convert_entries(entries)
    return entries if Map === entries
    if entries.respond_to?(:to_hash)
      entries = Hash.try_convert(entries)
      raise TypeError, "entries must be a Hash or respond to #to_hash" unless entries
    end
    return entries if entries.nil? || entries.respond_to?(:each)
    raise TypeError, "entries must yield key/value pairs with #each"
  end

  def each_for_inspect(&)                 = each(&)
  def inspect_pair(inspector, key, value) = inspector.hash_pair(key, value) { inspect_value(inspector, value) }
  def inspect_value(inspector, ...)       = inspector.object(...)
end

#each_pair ⇒ BasicObject

This method is abstract.

Iterate over key-value pairs in the same manner as #each.

See Also:



155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
# File 'lib/farce/abstract/map.rb', line 155

class Map
  include Internal::MarshalSupport::Map
  include Enumerable
  include Internal::Inspect

  # Store a value using the map's assignment operation.
  # Concurrent maps override this method to support timeouts.
  # @param key [BasicObject] the key to store
  # @param value [BasicObject] the value to store
  # @return [BasicObject] `value`
  def store(key, value) = self[key] = value

  # Return a two-element array containing a key and its associated value, if the key is present,
  # or nil if the key is absent.
  # @param key [BasicObject] The key to look up.
  # @return [Array(BasicObject, BasicObject), nil] A two-element `[key, value]` array, or nil if the key is absent.
  def assoc(key)
    value = fetch(key) { return nil }
    [key, value]
  end

  # (see #compare_keys_by_identity?)
  def compare_by_identity? = compare_keys_by_identity?

  # Implements Ruby's [dig interface](https://docs.ruby-lang.org/en/master/language/dig_methods_rdoc.html).
  # @param key [BasicObject] The key to look up.
  # @param rest [Array<BasicObject>] Additional keys to look up in nested maps.
  # @return [BasicObject, nil] The value found at the nested location, or nil if any key is absent or nil.
  def dig(key, *rest)
    value = self[key]
    return value if rest.empty? || value.nil?
    value.dig(*rest)
  end

  # Returns whether the map contains no entries.
  # @return [Boolean] Whether the map is empty.
  def empty? = size.zero?

  # Return the number of entries currently in the map.
  # @return [Integer]
  def length = size

  # Return whether an observed value matches using this map's value comparison setting.
  # Values are unwrapped before comparison. Concurrent changes may make the result stale.
  # @param value [BasicObject] the value to find
  # @return [Boolean]
  def value?(value)
    identity = compare_values_by_identity?
    each_value.any? { |stored| identity ? stored.equal?(value) : stored == value }
  end
  alias has_value? value?

  # Return a matching key using this map's value comparison setting, or nil.
  # The first observed match is returned. No insertion order is guaranteed.
  # @param value [BasicObject] the value to find
  # @return [BasicObject, nil]
  def key(value)
    pair = rassoc(value)
    pair&.first
  end

  # Return an observed key/value pair using this map's value comparison setting, or nil.
  # Values are unwrapped before comparison. Concurrent changes may make the result stale.
  # @param value [BasicObject] the value to find
  # @return [Array, nil]
  def rassoc(value)
    identity = compare_values_by_identity?
    each_pair do |key, stored|
      return [key, stored] if identity ? stored.equal?(value) : stored == value
    end
    nil
  end

  # Alias for {#key?}
  def has_key?(...) = key?(...) # rubocop:disable Naming/PredicatePrefix
  alias member?  has_key?
  alias include? has_key?

  # Fetches the values associated with multiple keys, using the same missing-key behavior as Hash#fetch.
  # @yield [key] Called for each missing key.
  # @yieldparam key [BasicObject] The missing key.
  # @yieldreturn [BasicObject] The value to return for the missing key.
  # @param keys [Array<BasicObject>] The keys to look up.
  # @return [Array<BasicObject>] An array of the associated values.
  def fetch_values(*keys, &) = keys.map { fetch(it, &) }

  # @note
  #   Some maps may still accept non-shareable keys or values, but convert them into shareable representations.
  #   This method will still return `true` for such maps.
  #
  # @return [Boolean] Whether the map requires keys to be Ractor-shareable
  def shareable_keys? = false

  # @return [Boolean] Whether the map requires values to be Ractor-shareable
  def shareable_values? = false

  # Creates a new Array containing the map's key-value pairs as two-element arrays.
  # @return [Array<Array(BasicObject, BasicObject)>>] A new Array of `[key, value]` arrays.
  def to_a = each_pair.to_a

  # Creates a new Hash containing the map's entries.
  # Preserves identity comparison for keys, including when a block transforms entries.
  # @yieldparam key [BasicObject] an existing key
  # @yieldparam value [BasicObject] its value
  # @yieldreturn [Array(BasicObject, BasicObject)] the key and value for the new Hash
  # @return [Hash] A new Hash with the original entries, or the pairs returned by the block.
  def to_h(&) = entries_to_hash(each_pair, &)

  # Support implicit Hash conversion using this map's {#to_h} implementation.
  # @return [Hash] A new Hash containing the map's entries.
  def to_hash = to_h

  # Support hash patterns using the same entries and key comparison as {#to_h}.
  # Like Hash, this returns all entries regardless of the requested keys.
  # @param keys [Array, nil] the optional key hint supplied by Ruby's pattern matcher
  # @return [Hash] A new Hash containing the map's entries.
  def deconstruct_keys(keys) = to_h # rubocop:disable Lint/UnusedMethodArgument

  # Fetches the values associated with multiple keys, returning nil for any missing keys.
  # @param keys [Array<BasicObject>] The keys to look up.
  # @return [Array<BasicObject>] An array of the associated values, with nil for any missing keys.
  def values_at(*keys) = keys.map { self[it] }

  # Some maps reference their keys weakly, automatically dropping entries when a key gets garbage-collected.
  # @return [Boolean] Whether the map uses weak references for keys.
  def weak_keys? = false

  # Some maps reference their values weakly, automatically dropping entries when a value gets garbage-collected.
  # @return [Boolean] Whether the map uses weak references for values.
  def weak_values? = false

  # @return [String] String representation of the map, suitable for debugging.
  def to_s = inspect

  # @api private
  def inspect_with(inspector)
    super do
      yield if block_given?
      inspector.breakable
      inspector.group("{", "}") do
        inspector.breakable ""
        inspector.seplist(self, nil, :each_for_inspect) do |key, value|
          inspector.group { inspect_pair(inspector, key, value) }
        end
      end
    end
  end

  protected

  # Convert a public value to its stored representation.
  # @api private
  def wrap_value(value) = value

  # Convert a stored representation to its public value.
  # @api private
  def unwrap_value(value) = value

  private

  def entries_to_hash(entries, &)
    return entries.to_h(&) unless compare_keys_by_identity?
    hash = {}.compare_by_identity
    entries.each do |key, value|
      if block_given?
        pair = Array.try_convert(yield(key, value))
        raise TypeError, "block must return an Array or respond to #to_ary" unless pair
        raise ArgumentError, "block must return a two-element pair" unless pair.size == 2
        key, value = pair
      end
      hash[key] = value
    end
    hash
  end

  def convert_entries(entries)
    return entries if Map === entries
    if entries.respond_to?(:to_hash)
      entries = Hash.try_convert(entries)
      raise TypeError, "entries must be a Hash or respond to #to_hash" unless entries
    end
    return entries if entries.nil? || entries.respond_to?(:each)
    raise TypeError, "entries must yield key/value pairs with #each"
  end

  def each_for_inspect(&)                 = each(&)
  def inspect_pair(inspector, key, value) = inspector.hash_pair(key, value) { inspect_value(inspector, value) }
  def inspect_value(inspector, ...)       = inspector.object(...)
end

#each_value {|value| ... } ⇒ self #each_value ⇒ Enumerator

This method is abstract.

Iterate over the values currently stored in the map. Values are not guaranteed to be yielded in insertion order.

Overloads:

  • #each_value {|value| ... } ⇒ self

    Yields:

    • (value) —

      Called once for each stored value.

    Yield Parameters:

    • value (BasicObject) —

      A stored value.

    Returns:

    • (self)
  • #each_value ⇒ Enumerator

    Returns An enumerator over the stored values.

    Returns:

    • (Enumerator) —

      An enumerator over the stored values.



155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
# File 'lib/farce/abstract/map.rb', line 155

class Map
  include Internal::MarshalSupport::Map
  include Enumerable
  include Internal::Inspect

  # Store a value using the map's assignment operation.
  # Concurrent maps override this method to support timeouts.
  # @param key [BasicObject] the key to store
  # @param value [BasicObject] the value to store
  # @return [BasicObject] `value`
  def store(key, value) = self[key] = value

  # Return a two-element array containing a key and its associated value, if the key is present,
  # or nil if the key is absent.
  # @param key [BasicObject] The key to look up.
  # @return [Array(BasicObject, BasicObject), nil] A two-element `[key, value]` array, or nil if the key is absent.
  def assoc(key)
    value = fetch(key) { return nil }
    [key, value]
  end

  # (see #compare_keys_by_identity?)
  def compare_by_identity? = compare_keys_by_identity?

  # Implements Ruby's [dig interface](https://docs.ruby-lang.org/en/master/language/dig_methods_rdoc.html).
  # @param key [BasicObject] The key to look up.
  # @param rest [Array<BasicObject>] Additional keys to look up in nested maps.
  # @return [BasicObject, nil] The value found at the nested location, or nil if any key is absent or nil.
  def dig(key, *rest)
    value = self[key]
    return value if rest.empty? || value.nil?
    value.dig(*rest)
  end

  # Returns whether the map contains no entries.
  # @return [Boolean] Whether the map is empty.
  def empty? = size.zero?

  # Return the number of entries currently in the map.
  # @return [Integer]
  def length = size

  # Return whether an observed value matches using this map's value comparison setting.
  # Values are unwrapped before comparison. Concurrent changes may make the result stale.
  # @param value [BasicObject] the value to find
  # @return [Boolean]
  def value?(value)
    identity = compare_values_by_identity?
    each_value.any? { |stored| identity ? stored.equal?(value) : stored == value }
  end
  alias has_value? value?

  # Return a matching key using this map's value comparison setting, or nil.
  # The first observed match is returned. No insertion order is guaranteed.
  # @param value [BasicObject] the value to find
  # @return [BasicObject, nil]
  def key(value)
    pair = rassoc(value)
    pair&.first
  end

  # Return an observed key/value pair using this map's value comparison setting, or nil.
  # Values are unwrapped before comparison. Concurrent changes may make the result stale.
  # @param value [BasicObject] the value to find
  # @return [Array, nil]
  def rassoc(value)
    identity = compare_values_by_identity?
    each_pair do |key, stored|
      return [key, stored] if identity ? stored.equal?(value) : stored == value
    end
    nil
  end

  # Alias for {#key?}
  def has_key?(...) = key?(...) # rubocop:disable Naming/PredicatePrefix
  alias member?  has_key?
  alias include? has_key?

  # Fetches the values associated with multiple keys, using the same missing-key behavior as Hash#fetch.
  # @yield [key] Called for each missing key.
  # @yieldparam key [BasicObject] The missing key.
  # @yieldreturn [BasicObject] The value to return for the missing key.
  # @param keys [Array<BasicObject>] The keys to look up.
  # @return [Array<BasicObject>] An array of the associated values.
  def fetch_values(*keys, &) = keys.map { fetch(it, &) }

  # @note
  #   Some maps may still accept non-shareable keys or values, but convert them into shareable representations.
  #   This method will still return `true` for such maps.
  #
  # @return [Boolean] Whether the map requires keys to be Ractor-shareable
  def shareable_keys? = false

  # @return [Boolean] Whether the map requires values to be Ractor-shareable
  def shareable_values? = false

  # Creates a new Array containing the map's key-value pairs as two-element arrays.
  # @return [Array<Array(BasicObject, BasicObject)>>] A new Array of `[key, value]` arrays.
  def to_a = each_pair.to_a

  # Creates a new Hash containing the map's entries.
  # Preserves identity comparison for keys, including when a block transforms entries.
  # @yieldparam key [BasicObject] an existing key
  # @yieldparam value [BasicObject] its value
  # @yieldreturn [Array(BasicObject, BasicObject)] the key and value for the new Hash
  # @return [Hash] A new Hash with the original entries, or the pairs returned by the block.
  def to_h(&) = entries_to_hash(each_pair, &)

  # Support implicit Hash conversion using this map's {#to_h} implementation.
  # @return [Hash] A new Hash containing the map's entries.
  def to_hash = to_h

  # Support hash patterns using the same entries and key comparison as {#to_h}.
  # Like Hash, this returns all entries regardless of the requested keys.
  # @param keys [Array, nil] the optional key hint supplied by Ruby's pattern matcher
  # @return [Hash] A new Hash containing the map's entries.
  def deconstruct_keys(keys) = to_h # rubocop:disable Lint/UnusedMethodArgument

  # Fetches the values associated with multiple keys, returning nil for any missing keys.
  # @param keys [Array<BasicObject>] The keys to look up.
  # @return [Array<BasicObject>] An array of the associated values, with nil for any missing keys.
  def values_at(*keys) = keys.map { self[it] }

  # Some maps reference their keys weakly, automatically dropping entries when a key gets garbage-collected.
  # @return [Boolean] Whether the map uses weak references for keys.
  def weak_keys? = false

  # Some maps reference their values weakly, automatically dropping entries when a value gets garbage-collected.
  # @return [Boolean] Whether the map uses weak references for values.
  def weak_values? = false

  # @return [String] String representation of the map, suitable for debugging.
  def to_s = inspect

  # @api private
  def inspect_with(inspector)
    super do
      yield if block_given?
      inspector.breakable
      inspector.group("{", "}") do
        inspector.breakable ""
        inspector.seplist(self, nil, :each_for_inspect) do |key, value|
          inspector.group { inspect_pair(inspector, key, value) }
        end
      end
    end
  end

  protected

  # Convert a public value to its stored representation.
  # @api private
  def wrap_value(value) = value

  # Convert a stored representation to its public value.
  # @api private
  def unwrap_value(value) = value

  private

  def entries_to_hash(entries, &)
    return entries.to_h(&) unless compare_keys_by_identity?
    hash = {}.compare_by_identity
    entries.each do |key, value|
      if block_given?
        pair = Array.try_convert(yield(key, value))
        raise TypeError, "block must return an Array or respond to #to_ary" unless pair
        raise ArgumentError, "block must return a two-element pair" unless pair.size == 2
        key, value = pair
      end
      hash[key] = value
    end
    hash
  end

  def convert_entries(entries)
    return entries if Map === entries
    if entries.respond_to?(:to_hash)
      entries = Hash.try_convert(entries)
      raise TypeError, "entries must be a Hash or respond to #to_hash" unless entries
    end
    return entries if entries.nil? || entries.respond_to?(:each)
    raise TypeError, "entries must yield key/value pairs with #each"
  end

  def each_for_inspect(&)                 = each(&)
  def inspect_pair(inspector, key, value) = inspector.hash_pair(key, value) { inspect_value(inspector, value) }
  def inspect_value(inspector, ...)       = inspector.object(...)
end

#empty? ⇒ Boolean

Returns whether the map contains no entries.

Returns:

  • (Boolean) —

    Whether the map is empty.



191
# File 'lib/farce/abstract/map.rb', line 191

def empty? = size.zero?

#fetch(key) ⇒ BasicObject #fetch(key, default) ⇒ BasicObject #fetch(key) {|key| ... } ⇒ BasicObject

This method is abstract.

Fetch the value associated with a key, using the same missing-key behavior as Hash#fetch. If both a default and a block are provided, the block takes precedence and a warning is emitted.

Overloads:

  • #fetch(key) ⇒ BasicObject

    Returns The associated value.

    Parameters:

    • key (BasicObject) —

      The key to look up.

    Returns:

    • (BasicObject) —

      The associated value.

    Raises:

    • (KeyError) —

      If the key is absent.

  • #fetch(key, default) ⇒ BasicObject

    Returns The associated value or default.

    Parameters:

    • key (BasicObject) —

      The key to look up.

    • default (BasicObject) —

      The value to return if the key is absent.

    Returns:

    • (BasicObject) —

      The associated value or default.

  • #fetch(key) {|key| ... } ⇒ BasicObject

    Returns The associated value or the block result.

    Parameters:

    • key (BasicObject) —

      The key to look up.

    Yields:

    • (key) —

      Called if the key is absent.

    Yield Parameters:

    • key (BasicObject) —

      The missing key.

    Yield Returns:

    • (BasicObject) —

      The value to return.

    Returns:

    • (BasicObject) —

      The associated value or the block result.



155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
# File 'lib/farce/abstract/map.rb', line 155

class Map
  include Internal::MarshalSupport::Map
  include Enumerable
  include Internal::Inspect

  # Store a value using the map's assignment operation.
  # Concurrent maps override this method to support timeouts.
  # @param key [BasicObject] the key to store
  # @param value [BasicObject] the value to store
  # @return [BasicObject] `value`
  def store(key, value) = self[key] = value

  # Return a two-element array containing a key and its associated value, if the key is present,
  # or nil if the key is absent.
  # @param key [BasicObject] The key to look up.
  # @return [Array(BasicObject, BasicObject), nil] A two-element `[key, value]` array, or nil if the key is absent.
  def assoc(key)
    value = fetch(key) { return nil }
    [key, value]
  end

  # (see #compare_keys_by_identity?)
  def compare_by_identity? = compare_keys_by_identity?

  # Implements Ruby's [dig interface](https://docs.ruby-lang.org/en/master/language/dig_methods_rdoc.html).
  # @param key [BasicObject] The key to look up.
  # @param rest [Array<BasicObject>] Additional keys to look up in nested maps.
  # @return [BasicObject, nil] The value found at the nested location, or nil if any key is absent or nil.
  def dig(key, *rest)
    value = self[key]
    return value if rest.empty? || value.nil?
    value.dig(*rest)
  end

  # Returns whether the map contains no entries.
  # @return [Boolean] Whether the map is empty.
  def empty? = size.zero?

  # Return the number of entries currently in the map.
  # @return [Integer]
  def length = size

  # Return whether an observed value matches using this map's value comparison setting.
  # Values are unwrapped before comparison. Concurrent changes may make the result stale.
  # @param value [BasicObject] the value to find
  # @return [Boolean]
  def value?(value)
    identity = compare_values_by_identity?
    each_value.any? { |stored| identity ? stored.equal?(value) : stored == value }
  end
  alias has_value? value?

  # Return a matching key using this map's value comparison setting, or nil.
  # The first observed match is returned. No insertion order is guaranteed.
  # @param value [BasicObject] the value to find
  # @return [BasicObject, nil]
  def key(value)
    pair = rassoc(value)
    pair&.first
  end

  # Return an observed key/value pair using this map's value comparison setting, or nil.
  # Values are unwrapped before comparison. Concurrent changes may make the result stale.
  # @param value [BasicObject] the value to find
  # @return [Array, nil]
  def rassoc(value)
    identity = compare_values_by_identity?
    each_pair do |key, stored|
      return [key, stored] if identity ? stored.equal?(value) : stored == value
    end
    nil
  end

  # Alias for {#key?}
  def has_key?(...) = key?(...) # rubocop:disable Naming/PredicatePrefix
  alias member?  has_key?
  alias include? has_key?

  # Fetches the values associated with multiple keys, using the same missing-key behavior as Hash#fetch.
  # @yield [key] Called for each missing key.
  # @yieldparam key [BasicObject] The missing key.
  # @yieldreturn [BasicObject] The value to return for the missing key.
  # @param keys [Array<BasicObject>] The keys to look up.
  # @return [Array<BasicObject>] An array of the associated values.
  def fetch_values(*keys, &) = keys.map { fetch(it, &) }

  # @note
  #   Some maps may still accept non-shareable keys or values, but convert them into shareable representations.
  #   This method will still return `true` for such maps.
  #
  # @return [Boolean] Whether the map requires keys to be Ractor-shareable
  def shareable_keys? = false

  # @return [Boolean] Whether the map requires values to be Ractor-shareable
  def shareable_values? = false

  # Creates a new Array containing the map's key-value pairs as two-element arrays.
  # @return [Array<Array(BasicObject, BasicObject)>>] A new Array of `[key, value]` arrays.
  def to_a = each_pair.to_a

  # Creates a new Hash containing the map's entries.
  # Preserves identity comparison for keys, including when a block transforms entries.
  # @yieldparam key [BasicObject] an existing key
  # @yieldparam value [BasicObject] its value
  # @yieldreturn [Array(BasicObject, BasicObject)] the key and value for the new Hash
  # @return [Hash] A new Hash with the original entries, or the pairs returned by the block.
  def to_h(&) = entries_to_hash(each_pair, &)

  # Support implicit Hash conversion using this map's {#to_h} implementation.
  # @return [Hash] A new Hash containing the map's entries.
  def to_hash = to_h

  # Support hash patterns using the same entries and key comparison as {#to_h}.
  # Like Hash, this returns all entries regardless of the requested keys.
  # @param keys [Array, nil] the optional key hint supplied by Ruby's pattern matcher
  # @return [Hash] A new Hash containing the map's entries.
  def deconstruct_keys(keys) = to_h # rubocop:disable Lint/UnusedMethodArgument

  # Fetches the values associated with multiple keys, returning nil for any missing keys.
  # @param keys [Array<BasicObject>] The keys to look up.
  # @return [Array<BasicObject>] An array of the associated values, with nil for any missing keys.
  def values_at(*keys) = keys.map { self[it] }

  # Some maps reference their keys weakly, automatically dropping entries when a key gets garbage-collected.
  # @return [Boolean] Whether the map uses weak references for keys.
  def weak_keys? = false

  # Some maps reference their values weakly, automatically dropping entries when a value gets garbage-collected.
  # @return [Boolean] Whether the map uses weak references for values.
  def weak_values? = false

  # @return [String] String representation of the map, suitable for debugging.
  def to_s = inspect

  # @api private
  def inspect_with(inspector)
    super do
      yield if block_given?
      inspector.breakable
      inspector.group("{", "}") do
        inspector.breakable ""
        inspector.seplist(self, nil, :each_for_inspect) do |key, value|
          inspector.group { inspect_pair(inspector, key, value) }
        end
      end
    end
  end

  protected

  # Convert a public value to its stored representation.
  # @api private
  def wrap_value(value) = value

  # Convert a stored representation to its public value.
  # @api private
  def unwrap_value(value) = value

  private

  def entries_to_hash(entries, &)
    return entries.to_h(&) unless compare_keys_by_identity?
    hash = {}.compare_by_identity
    entries.each do |key, value|
      if block_given?
        pair = Array.try_convert(yield(key, value))
        raise TypeError, "block must return an Array or respond to #to_ary" unless pair
        raise ArgumentError, "block must return a two-element pair" unless pair.size == 2
        key, value = pair
      end
      hash[key] = value
    end
    hash
  end

  def convert_entries(entries)
    return entries if Map === entries
    if entries.respond_to?(:to_hash)
      entries = Hash.try_convert(entries)
      raise TypeError, "entries must be a Hash or respond to #to_hash" unless entries
    end
    return entries if entries.nil? || entries.respond_to?(:each)
    raise TypeError, "entries must yield key/value pairs with #each"
  end

  def each_for_inspect(&)                 = each(&)
  def inspect_pair(inspector, key, value) = inspector.hash_pair(key, value) { inspect_value(inspector, value) }
  def inspect_value(inspector, ...)       = inspector.object(...)
end

#fetch_values(*keys) {|key| ... } ⇒ Array<BasicObject>

Fetches the values associated with multiple keys, using the same missing-key behavior as Hash#fetch.

Parameters:

  • keys (Array<BasicObject>) —

    The keys to look up.

Yields:

  • (key) —

    Called for each missing key.

Yield Parameters:

  • key (BasicObject) —

    The missing key.

Yield Returns:

  • (BasicObject) —

    The value to return for the missing key.

Returns:

  • (Array<BasicObject>) —

    An array of the associated values.



239
# File 'lib/farce/abstract/map.rb', line 239

def fetch_values(*keys, &) = keys.map { fetch(it, &) }

#getkey(key) ⇒ BasicObject?

This method is abstract.

Return the stored key that matches a lookup key.

Parameters:

  • key (BasicObject) —

    The key to match.

Returns:

  • (BasicObject, nil) —

    The matching stored key, or nil if no key matches.



155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
# File 'lib/farce/abstract/map.rb', line 155

class Map
  include Internal::MarshalSupport::Map
  include Enumerable
  include Internal::Inspect

  # Store a value using the map's assignment operation.
  # Concurrent maps override this method to support timeouts.
  # @param key [BasicObject] the key to store
  # @param value [BasicObject] the value to store
  # @return [BasicObject] `value`
  def store(key, value) = self[key] = value

  # Return a two-element array containing a key and its associated value, if the key is present,
  # or nil if the key is absent.
  # @param key [BasicObject] The key to look up.
  # @return [Array(BasicObject, BasicObject), nil] A two-element `[key, value]` array, or nil if the key is absent.
  def assoc(key)
    value = fetch(key) { return nil }
    [key, value]
  end

  # (see #compare_keys_by_identity?)
  def compare_by_identity? = compare_keys_by_identity?

  # Implements Ruby's [dig interface](https://docs.ruby-lang.org/en/master/language/dig_methods_rdoc.html).
  # @param key [BasicObject] The key to look up.
  # @param rest [Array<BasicObject>] Additional keys to look up in nested maps.
  # @return [BasicObject, nil] The value found at the nested location, or nil if any key is absent or nil.
  def dig(key, *rest)
    value = self[key]
    return value if rest.empty? || value.nil?
    value.dig(*rest)
  end

  # Returns whether the map contains no entries.
  # @return [Boolean] Whether the map is empty.
  def empty? = size.zero?

  # Return the number of entries currently in the map.
  # @return [Integer]
  def length = size

  # Return whether an observed value matches using this map's value comparison setting.
  # Values are unwrapped before comparison. Concurrent changes may make the result stale.
  # @param value [BasicObject] the value to find
  # @return [Boolean]
  def value?(value)
    identity = compare_values_by_identity?
    each_value.any? { |stored| identity ? stored.equal?(value) : stored == value }
  end
  alias has_value? value?

  # Return a matching key using this map's value comparison setting, or nil.
  # The first observed match is returned. No insertion order is guaranteed.
  # @param value [BasicObject] the value to find
  # @return [BasicObject, nil]
  def key(value)
    pair = rassoc(value)
    pair&.first
  end

  # Return an observed key/value pair using this map's value comparison setting, or nil.
  # Values are unwrapped before comparison. Concurrent changes may make the result stale.
  # @param value [BasicObject] the value to find
  # @return [Array, nil]
  def rassoc(value)
    identity = compare_values_by_identity?
    each_pair do |key, stored|
      return [key, stored] if identity ? stored.equal?(value) : stored == value
    end
    nil
  end

  # Alias for {#key?}
  def has_key?(...) = key?(...) # rubocop:disable Naming/PredicatePrefix
  alias member?  has_key?
  alias include? has_key?

  # Fetches the values associated with multiple keys, using the same missing-key behavior as Hash#fetch.
  # @yield [key] Called for each missing key.
  # @yieldparam key [BasicObject] The missing key.
  # @yieldreturn [BasicObject] The value to return for the missing key.
  # @param keys [Array<BasicObject>] The keys to look up.
  # @return [Array<BasicObject>] An array of the associated values.
  def fetch_values(*keys, &) = keys.map { fetch(it, &) }

  # @note
  #   Some maps may still accept non-shareable keys or values, but convert them into shareable representations.
  #   This method will still return `true` for such maps.
  #
  # @return [Boolean] Whether the map requires keys to be Ractor-shareable
  def shareable_keys? = false

  # @return [Boolean] Whether the map requires values to be Ractor-shareable
  def shareable_values? = false

  # Creates a new Array containing the map's key-value pairs as two-element arrays.
  # @return [Array<Array(BasicObject, BasicObject)>>] A new Array of `[key, value]` arrays.
  def to_a = each_pair.to_a

  # Creates a new Hash containing the map's entries.
  # Preserves identity comparison for keys, including when a block transforms entries.
  # @yieldparam key [BasicObject] an existing key
  # @yieldparam value [BasicObject] its value
  # @yieldreturn [Array(BasicObject, BasicObject)] the key and value for the new Hash
  # @return [Hash] A new Hash with the original entries, or the pairs returned by the block.
  def to_h(&) = entries_to_hash(each_pair, &)

  # Support implicit Hash conversion using this map's {#to_h} implementation.
  # @return [Hash] A new Hash containing the map's entries.
  def to_hash = to_h

  # Support hash patterns using the same entries and key comparison as {#to_h}.
  # Like Hash, this returns all entries regardless of the requested keys.
  # @param keys [Array, nil] the optional key hint supplied by Ruby's pattern matcher
  # @return [Hash] A new Hash containing the map's entries.
  def deconstruct_keys(keys) = to_h # rubocop:disable Lint/UnusedMethodArgument

  # Fetches the values associated with multiple keys, returning nil for any missing keys.
  # @param keys [Array<BasicObject>] The keys to look up.
  # @return [Array<BasicObject>] An array of the associated values, with nil for any missing keys.
  def values_at(*keys) = keys.map { self[it] }

  # Some maps reference their keys weakly, automatically dropping entries when a key gets garbage-collected.
  # @return [Boolean] Whether the map uses weak references for keys.
  def weak_keys? = false

  # Some maps reference their values weakly, automatically dropping entries when a value gets garbage-collected.
  # @return [Boolean] Whether the map uses weak references for values.
  def weak_values? = false

  # @return [String] String representation of the map, suitable for debugging.
  def to_s = inspect

  # @api private
  def inspect_with(inspector)
    super do
      yield if block_given?
      inspector.breakable
      inspector.group("{", "}") do
        inspector.breakable ""
        inspector.seplist(self, nil, :each_for_inspect) do |key, value|
          inspector.group { inspect_pair(inspector, key, value) }
        end
      end
    end
  end

  protected

  # Convert a public value to its stored representation.
  # @api private
  def wrap_value(value) = value

  # Convert a stored representation to its public value.
  # @api private
  def unwrap_value(value) = value

  private

  def entries_to_hash(entries, &)
    return entries.to_h(&) unless compare_keys_by_identity?
    hash = {}.compare_by_identity
    entries.each do |key, value|
      if block_given?
        pair = Array.try_convert(yield(key, value))
        raise TypeError, "block must return an Array or respond to #to_ary" unless pair
        raise ArgumentError, "block must return a two-element pair" unless pair.size == 2
        key, value = pair
      end
      hash[key] = value
    end
    hash
  end

  def convert_entries(entries)
    return entries if Map === entries
    if entries.respond_to?(:to_hash)
      entries = Hash.try_convert(entries)
      raise TypeError, "entries must be a Hash or respond to #to_hash" unless entries
    end
    return entries if entries.nil? || entries.respond_to?(:each)
    raise TypeError, "entries must yield key/value pairs with #each"
  end

  def each_for_inspect(&)                 = each(&)
  def inspect_pair(inspector, key, value) = inspector.hash_pair(key, value) { inspect_value(inspector, value) }
  def inspect_value(inspector, ...)       = inspector.object(...)
end

#has_key? ⇒ Boolean Also known as: member?, include?

Alias for #key?

Returns:

  • (Boolean)


229
# File 'lib/farce/abstract/map.rb', line 229

def has_key?(...) = key?(...) # rubocop:disable Naming/PredicatePrefix

#key(value) ⇒ BasicObject?

Return a matching key using this map's value comparison setting, or nil. The first observed match is returned. No insertion order is guaranteed.

Parameters:

  • value (BasicObject) —

    the value to find

Returns:

  • (BasicObject, nil)


211
212
213
214
# File 'lib/farce/abstract/map.rb', line 211

def key(value)
  pair = rassoc(value)
  pair&.first
end

#key?(key) ⇒ Boolean

This method is abstract.

Test whether a key is present, including when its associated value is nil.

Parameters:

  • key (BasicObject) —

    The key to look up.

Returns:

  • (Boolean) —

    Whether the key is present.



155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
# File 'lib/farce/abstract/map.rb', line 155

class Map
  include Internal::MarshalSupport::Map
  include Enumerable
  include Internal::Inspect

  # Store a value using the map's assignment operation.
  # Concurrent maps override this method to support timeouts.
  # @param key [BasicObject] the key to store
  # @param value [BasicObject] the value to store
  # @return [BasicObject] `value`
  def store(key, value) = self[key] = value

  # Return a two-element array containing a key and its associated value, if the key is present,
  # or nil if the key is absent.
  # @param key [BasicObject] The key to look up.
  # @return [Array(BasicObject, BasicObject), nil] A two-element `[key, value]` array, or nil if the key is absent.
  def assoc(key)
    value = fetch(key) { return nil }
    [key, value]
  end

  # (see #compare_keys_by_identity?)
  def compare_by_identity? = compare_keys_by_identity?

  # Implements Ruby's [dig interface](https://docs.ruby-lang.org/en/master/language/dig_methods_rdoc.html).
  # @param key [BasicObject] The key to look up.
  # @param rest [Array<BasicObject>] Additional keys to look up in nested maps.
  # @return [BasicObject, nil] The value found at the nested location, or nil if any key is absent or nil.
  def dig(key, *rest)
    value = self[key]
    return value if rest.empty? || value.nil?
    value.dig(*rest)
  end

  # Returns whether the map contains no entries.
  # @return [Boolean] Whether the map is empty.
  def empty? = size.zero?

  # Return the number of entries currently in the map.
  # @return [Integer]
  def length = size

  # Return whether an observed value matches using this map's value comparison setting.
  # Values are unwrapped before comparison. Concurrent changes may make the result stale.
  # @param value [BasicObject] the value to find
  # @return [Boolean]
  def value?(value)
    identity = compare_values_by_identity?
    each_value.any? { |stored| identity ? stored.equal?(value) : stored == value }
  end
  alias has_value? value?

  # Return a matching key using this map's value comparison setting, or nil.
  # The first observed match is returned. No insertion order is guaranteed.
  # @param value [BasicObject] the value to find
  # @return [BasicObject, nil]
  def key(value)
    pair = rassoc(value)
    pair&.first
  end

  # Return an observed key/value pair using this map's value comparison setting, or nil.
  # Values are unwrapped before comparison. Concurrent changes may make the result stale.
  # @param value [BasicObject] the value to find
  # @return [Array, nil]
  def rassoc(value)
    identity = compare_values_by_identity?
    each_pair do |key, stored|
      return [key, stored] if identity ? stored.equal?(value) : stored == value
    end
    nil
  end

  # Alias for {#key?}
  def has_key?(...) = key?(...) # rubocop:disable Naming/PredicatePrefix
  alias member?  has_key?
  alias include? has_key?

  # Fetches the values associated with multiple keys, using the same missing-key behavior as Hash#fetch.
  # @yield [key] Called for each missing key.
  # @yieldparam key [BasicObject] The missing key.
  # @yieldreturn [BasicObject] The value to return for the missing key.
  # @param keys [Array<BasicObject>] The keys to look up.
  # @return [Array<BasicObject>] An array of the associated values.
  def fetch_values(*keys, &) = keys.map { fetch(it, &) }

  # @note
  #   Some maps may still accept non-shareable keys or values, but convert them into shareable representations.
  #   This method will still return `true` for such maps.
  #
  # @return [Boolean] Whether the map requires keys to be Ractor-shareable
  def shareable_keys? = false

  # @return [Boolean] Whether the map requires values to be Ractor-shareable
  def shareable_values? = false

  # Creates a new Array containing the map's key-value pairs as two-element arrays.
  # @return [Array<Array(BasicObject, BasicObject)>>] A new Array of `[key, value]` arrays.
  def to_a = each_pair.to_a

  # Creates a new Hash containing the map's entries.
  # Preserves identity comparison for keys, including when a block transforms entries.
  # @yieldparam key [BasicObject] an existing key
  # @yieldparam value [BasicObject] its value
  # @yieldreturn [Array(BasicObject, BasicObject)] the key and value for the new Hash
  # @return [Hash] A new Hash with the original entries, or the pairs returned by the block.
  def to_h(&) = entries_to_hash(each_pair, &)

  # Support implicit Hash conversion using this map's {#to_h} implementation.
  # @return [Hash] A new Hash containing the map's entries.
  def to_hash = to_h

  # Support hash patterns using the same entries and key comparison as {#to_h}.
  # Like Hash, this returns all entries regardless of the requested keys.
  # @param keys [Array, nil] the optional key hint supplied by Ruby's pattern matcher
  # @return [Hash] A new Hash containing the map's entries.
  def deconstruct_keys(keys) = to_h # rubocop:disable Lint/UnusedMethodArgument

  # Fetches the values associated with multiple keys, returning nil for any missing keys.
  # @param keys [Array<BasicObject>] The keys to look up.
  # @return [Array<BasicObject>] An array of the associated values, with nil for any missing keys.
  def values_at(*keys) = keys.map { self[it] }

  # Some maps reference their keys weakly, automatically dropping entries when a key gets garbage-collected.
  # @return [Boolean] Whether the map uses weak references for keys.
  def weak_keys? = false

  # Some maps reference their values weakly, automatically dropping entries when a value gets garbage-collected.
  # @return [Boolean] Whether the map uses weak references for values.
  def weak_values? = false

  # @return [String] String representation of the map, suitable for debugging.
  def to_s = inspect

  # @api private
  def inspect_with(inspector)
    super do
      yield if block_given?
      inspector.breakable
      inspector.group("{", "}") do
        inspector.breakable ""
        inspector.seplist(self, nil, :each_for_inspect) do |key, value|
          inspector.group { inspect_pair(inspector, key, value) }
        end
      end
    end
  end

  protected

  # Convert a public value to its stored representation.
  # @api private
  def wrap_value(value) = value

  # Convert a stored representation to its public value.
  # @api private
  def unwrap_value(value) = value

  private

  def entries_to_hash(entries, &)
    return entries.to_h(&) unless compare_keys_by_identity?
    hash = {}.compare_by_identity
    entries.each do |key, value|
      if block_given?
        pair = Array.try_convert(yield(key, value))
        raise TypeError, "block must return an Array or respond to #to_ary" unless pair
        raise ArgumentError, "block must return a two-element pair" unless pair.size == 2
        key, value = pair
      end
      hash[key] = value
    end
    hash
  end

  def convert_entries(entries)
    return entries if Map === entries
    if entries.respond_to?(:to_hash)
      entries = Hash.try_convert(entries)
      raise TypeError, "entries must be a Hash or respond to #to_hash" unless entries
    end
    return entries if entries.nil? || entries.respond_to?(:each)
    raise TypeError, "entries must yield key/value pairs with #each"
  end

  def each_for_inspect(&)                 = each(&)
  def inspect_pair(inspector, key, value) = inspector.hash_pair(key, value) { inspect_value(inspector, value) }
  def inspect_value(inspector, ...)       = inspector.object(...)
end

#keys ⇒ Array<BasicObject>

This method is abstract.

Return the keys currently stored in the map. The returned keys are not guaranteed to be in insertion order.

Returns:

  • (Array<BasicObject>) —

    A new array containing the stored keys.



155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
# File 'lib/farce/abstract/map.rb', line 155

class Map
  include Internal::MarshalSupport::Map
  include Enumerable
  include Internal::Inspect

  # Store a value using the map's assignment operation.
  # Concurrent maps override this method to support timeouts.
  # @param key [BasicObject] the key to store
  # @param value [BasicObject] the value to store
  # @return [BasicObject] `value`
  def store(key, value) = self[key] = value

  # Return a two-element array containing a key and its associated value, if the key is present,
  # or nil if the key is absent.
  # @param key [BasicObject] The key to look up.
  # @return [Array(BasicObject, BasicObject), nil] A two-element `[key, value]` array, or nil if the key is absent.
  def assoc(key)
    value = fetch(key) { return nil }
    [key, value]
  end

  # (see #compare_keys_by_identity?)
  def compare_by_identity? = compare_keys_by_identity?

  # Implements Ruby's [dig interface](https://docs.ruby-lang.org/en/master/language/dig_methods_rdoc.html).
  # @param key [BasicObject] The key to look up.
  # @param rest [Array<BasicObject>] Additional keys to look up in nested maps.
  # @return [BasicObject, nil] The value found at the nested location, or nil if any key is absent or nil.
  def dig(key, *rest)
    value = self[key]
    return value if rest.empty? || value.nil?
    value.dig(*rest)
  end

  # Returns whether the map contains no entries.
  # @return [Boolean] Whether the map is empty.
  def empty? = size.zero?

  # Return the number of entries currently in the map.
  # @return [Integer]
  def length = size

  # Return whether an observed value matches using this map's value comparison setting.
  # Values are unwrapped before comparison. Concurrent changes may make the result stale.
  # @param value [BasicObject] the value to find
  # @return [Boolean]
  def value?(value)
    identity = compare_values_by_identity?
    each_value.any? { |stored| identity ? stored.equal?(value) : stored == value }
  end
  alias has_value? value?

  # Return a matching key using this map's value comparison setting, or nil.
  # The first observed match is returned. No insertion order is guaranteed.
  # @param value [BasicObject] the value to find
  # @return [BasicObject, nil]
  def key(value)
    pair = rassoc(value)
    pair&.first
  end

  # Return an observed key/value pair using this map's value comparison setting, or nil.
  # Values are unwrapped before comparison. Concurrent changes may make the result stale.
  # @param value [BasicObject] the value to find
  # @return [Array, nil]
  def rassoc(value)
    identity = compare_values_by_identity?
    each_pair do |key, stored|
      return [key, stored] if identity ? stored.equal?(value) : stored == value
    end
    nil
  end

  # Alias for {#key?}
  def has_key?(...) = key?(...) # rubocop:disable Naming/PredicatePrefix
  alias member?  has_key?
  alias include? has_key?

  # Fetches the values associated with multiple keys, using the same missing-key behavior as Hash#fetch.
  # @yield [key] Called for each missing key.
  # @yieldparam key [BasicObject] The missing key.
  # @yieldreturn [BasicObject] The value to return for the missing key.
  # @param keys [Array<BasicObject>] The keys to look up.
  # @return [Array<BasicObject>] An array of the associated values.
  def fetch_values(*keys, &) = keys.map { fetch(it, &) }

  # @note
  #   Some maps may still accept non-shareable keys or values, but convert them into shareable representations.
  #   This method will still return `true` for such maps.
  #
  # @return [Boolean] Whether the map requires keys to be Ractor-shareable
  def shareable_keys? = false

  # @return [Boolean] Whether the map requires values to be Ractor-shareable
  def shareable_values? = false

  # Creates a new Array containing the map's key-value pairs as two-element arrays.
  # @return [Array<Array(BasicObject, BasicObject)>>] A new Array of `[key, value]` arrays.
  def to_a = each_pair.to_a

  # Creates a new Hash containing the map's entries.
  # Preserves identity comparison for keys, including when a block transforms entries.
  # @yieldparam key [BasicObject] an existing key
  # @yieldparam value [BasicObject] its value
  # @yieldreturn [Array(BasicObject, BasicObject)] the key and value for the new Hash
  # @return [Hash] A new Hash with the original entries, or the pairs returned by the block.
  def to_h(&) = entries_to_hash(each_pair, &)

  # Support implicit Hash conversion using this map's {#to_h} implementation.
  # @return [Hash] A new Hash containing the map's entries.
  def to_hash = to_h

  # Support hash patterns using the same entries and key comparison as {#to_h}.
  # Like Hash, this returns all entries regardless of the requested keys.
  # @param keys [Array, nil] the optional key hint supplied by Ruby's pattern matcher
  # @return [Hash] A new Hash containing the map's entries.
  def deconstruct_keys(keys) = to_h # rubocop:disable Lint/UnusedMethodArgument

  # Fetches the values associated with multiple keys, returning nil for any missing keys.
  # @param keys [Array<BasicObject>] The keys to look up.
  # @return [Array<BasicObject>] An array of the associated values, with nil for any missing keys.
  def values_at(*keys) = keys.map { self[it] }

  # Some maps reference their keys weakly, automatically dropping entries when a key gets garbage-collected.
  # @return [Boolean] Whether the map uses weak references for keys.
  def weak_keys? = false

  # Some maps reference their values weakly, automatically dropping entries when a value gets garbage-collected.
  # @return [Boolean] Whether the map uses weak references for values.
  def weak_values? = false

  # @return [String] String representation of the map, suitable for debugging.
  def to_s = inspect

  # @api private
  def inspect_with(inspector)
    super do
      yield if block_given?
      inspector.breakable
      inspector.group("{", "}") do
        inspector.breakable ""
        inspector.seplist(self, nil, :each_for_inspect) do |key, value|
          inspector.group { inspect_pair(inspector, key, value) }
        end
      end
    end
  end

  protected

  # Convert a public value to its stored representation.
  # @api private
  def wrap_value(value) = value

  # Convert a stored representation to its public value.
  # @api private
  def unwrap_value(value) = value

  private

  def entries_to_hash(entries, &)
    return entries.to_h(&) unless compare_keys_by_identity?
    hash = {}.compare_by_identity
    entries.each do |key, value|
      if block_given?
        pair = Array.try_convert(yield(key, value))
        raise TypeError, "block must return an Array or respond to #to_ary" unless pair
        raise ArgumentError, "block must return a two-element pair" unless pair.size == 2
        key, value = pair
      end
      hash[key] = value
    end
    hash
  end

  def convert_entries(entries)
    return entries if Map === entries
    if entries.respond_to?(:to_hash)
      entries = Hash.try_convert(entries)
      raise TypeError, "entries must be a Hash or respond to #to_hash" unless entries
    end
    return entries if entries.nil? || entries.respond_to?(:each)
    raise TypeError, "entries must yield key/value pairs with #each"
  end

  def each_for_inspect(&)                 = each(&)
  def inspect_pair(inspector, key, value) = inspector.hash_pair(key, value) { inspect_value(inspector, value) }
  def inspect_value(inspector, ...)       = inspector.object(...)
end

#length ⇒ Integer

Return the number of entries currently in the map.

Returns:

  • (Integer)


195
# File 'lib/farce/abstract/map.rb', line 195

def length = size

#rassoc(value) ⇒ Array?

Return an observed key/value pair using this map's value comparison setting, or nil. Values are unwrapped before comparison. Concurrent changes may make the result stale.

Parameters:

  • value (BasicObject) —

    the value to find

Returns:

  • (Array, nil)


220
221
222
223
224
225
226
# File 'lib/farce/abstract/map.rb', line 220

def rassoc(value)
  identity = compare_values_by_identity?
  each_pair do |key, stored|
    return [key, stored] if identity ? stored.equal?(value) : stored == value
  end
  nil
end

#shareable_keys? ⇒ Boolean

Note:

Some maps may still accept non-shareable keys or values, but convert them into shareable representations. This method will still return true for such maps.

Returns Whether the map requires keys to be Ractor-shareable.

Returns:

  • (Boolean) —

    Whether the map requires keys to be Ractor-shareable



246
# File 'lib/farce/abstract/map.rb', line 246

def shareable_keys? = false

#shareable_values? ⇒ Boolean

Returns Whether the map requires values to be Ractor-shareable.

Returns:

  • (Boolean) —

    Whether the map requires values to be Ractor-shareable



249
# File 'lib/farce/abstract/map.rb', line 249

def shareable_values? = false

#size ⇒ Integer

This method is abstract.

Return the number of entries currently in the map.

Returns:

  • (Integer) —

    The number of entries.



155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
# File 'lib/farce/abstract/map.rb', line 155

class Map
  include Internal::MarshalSupport::Map
  include Enumerable
  include Internal::Inspect

  # Store a value using the map's assignment operation.
  # Concurrent maps override this method to support timeouts.
  # @param key [BasicObject] the key to store
  # @param value [BasicObject] the value to store
  # @return [BasicObject] `value`
  def store(key, value) = self[key] = value

  # Return a two-element array containing a key and its associated value, if the key is present,
  # or nil if the key is absent.
  # @param key [BasicObject] The key to look up.
  # @return [Array(BasicObject, BasicObject), nil] A two-element `[key, value]` array, or nil if the key is absent.
  def assoc(key)
    value = fetch(key) { return nil }
    [key, value]
  end

  # (see #compare_keys_by_identity?)
  def compare_by_identity? = compare_keys_by_identity?

  # Implements Ruby's [dig interface](https://docs.ruby-lang.org/en/master/language/dig_methods_rdoc.html).
  # @param key [BasicObject] The key to look up.
  # @param rest [Array<BasicObject>] Additional keys to look up in nested maps.
  # @return [BasicObject, nil] The value found at the nested location, or nil if any key is absent or nil.
  def dig(key, *rest)
    value = self[key]
    return value if rest.empty? || value.nil?
    value.dig(*rest)
  end

  # Returns whether the map contains no entries.
  # @return [Boolean] Whether the map is empty.
  def empty? = size.zero?

  # Return the number of entries currently in the map.
  # @return [Integer]
  def length = size

  # Return whether an observed value matches using this map's value comparison setting.
  # Values are unwrapped before comparison. Concurrent changes may make the result stale.
  # @param value [BasicObject] the value to find
  # @return [Boolean]
  def value?(value)
    identity = compare_values_by_identity?
    each_value.any? { |stored| identity ? stored.equal?(value) : stored == value }
  end
  alias has_value? value?

  # Return a matching key using this map's value comparison setting, or nil.
  # The first observed match is returned. No insertion order is guaranteed.
  # @param value [BasicObject] the value to find
  # @return [BasicObject, nil]
  def key(value)
    pair = rassoc(value)
    pair&.first
  end

  # Return an observed key/value pair using this map's value comparison setting, or nil.
  # Values are unwrapped before comparison. Concurrent changes may make the result stale.
  # @param value [BasicObject] the value to find
  # @return [Array, nil]
  def rassoc(value)
    identity = compare_values_by_identity?
    each_pair do |key, stored|
      return [key, stored] if identity ? stored.equal?(value) : stored == value
    end
    nil
  end

  # Alias for {#key?}
  def has_key?(...) = key?(...) # rubocop:disable Naming/PredicatePrefix
  alias member?  has_key?
  alias include? has_key?

  # Fetches the values associated with multiple keys, using the same missing-key behavior as Hash#fetch.
  # @yield [key] Called for each missing key.
  # @yieldparam key [BasicObject] The missing key.
  # @yieldreturn [BasicObject] The value to return for the missing key.
  # @param keys [Array<BasicObject>] The keys to look up.
  # @return [Array<BasicObject>] An array of the associated values.
  def fetch_values(*keys, &) = keys.map { fetch(it, &) }

  # @note
  #   Some maps may still accept non-shareable keys or values, but convert them into shareable representations.
  #   This method will still return `true` for such maps.
  #
  # @return [Boolean] Whether the map requires keys to be Ractor-shareable
  def shareable_keys? = false

  # @return [Boolean] Whether the map requires values to be Ractor-shareable
  def shareable_values? = false

  # Creates a new Array containing the map's key-value pairs as two-element arrays.
  # @return [Array<Array(BasicObject, BasicObject)>>] A new Array of `[key, value]` arrays.
  def to_a = each_pair.to_a

  # Creates a new Hash containing the map's entries.
  # Preserves identity comparison for keys, including when a block transforms entries.
  # @yieldparam key [BasicObject] an existing key
  # @yieldparam value [BasicObject] its value
  # @yieldreturn [Array(BasicObject, BasicObject)] the key and value for the new Hash
  # @return [Hash] A new Hash with the original entries, or the pairs returned by the block.
  def to_h(&) = entries_to_hash(each_pair, &)

  # Support implicit Hash conversion using this map's {#to_h} implementation.
  # @return [Hash] A new Hash containing the map's entries.
  def to_hash = to_h

  # Support hash patterns using the same entries and key comparison as {#to_h}.
  # Like Hash, this returns all entries regardless of the requested keys.
  # @param keys [Array, nil] the optional key hint supplied by Ruby's pattern matcher
  # @return [Hash] A new Hash containing the map's entries.
  def deconstruct_keys(keys) = to_h # rubocop:disable Lint/UnusedMethodArgument

  # Fetches the values associated with multiple keys, returning nil for any missing keys.
  # @param keys [Array<BasicObject>] The keys to look up.
  # @return [Array<BasicObject>] An array of the associated values, with nil for any missing keys.
  def values_at(*keys) = keys.map { self[it] }

  # Some maps reference their keys weakly, automatically dropping entries when a key gets garbage-collected.
  # @return [Boolean] Whether the map uses weak references for keys.
  def weak_keys? = false

  # Some maps reference their values weakly, automatically dropping entries when a value gets garbage-collected.
  # @return [Boolean] Whether the map uses weak references for values.
  def weak_values? = false

  # @return [String] String representation of the map, suitable for debugging.
  def to_s = inspect

  # @api private
  def inspect_with(inspector)
    super do
      yield if block_given?
      inspector.breakable
      inspector.group("{", "}") do
        inspector.breakable ""
        inspector.seplist(self, nil, :each_for_inspect) do |key, value|
          inspector.group { inspect_pair(inspector, key, value) }
        end
      end
    end
  end

  protected

  # Convert a public value to its stored representation.
  # @api private
  def wrap_value(value) = value

  # Convert a stored representation to its public value.
  # @api private
  def unwrap_value(value) = value

  private

  def entries_to_hash(entries, &)
    return entries.to_h(&) unless compare_keys_by_identity?
    hash = {}.compare_by_identity
    entries.each do |key, value|
      if block_given?
        pair = Array.try_convert(yield(key, value))
        raise TypeError, "block must return an Array or respond to #to_ary" unless pair
        raise ArgumentError, "block must return a two-element pair" unless pair.size == 2
        key, value = pair
      end
      hash[key] = value
    end
    hash
  end

  def convert_entries(entries)
    return entries if Map === entries
    if entries.respond_to?(:to_hash)
      entries = Hash.try_convert(entries)
      raise TypeError, "entries must be a Hash or respond to #to_hash" unless entries
    end
    return entries if entries.nil? || entries.respond_to?(:each)
    raise TypeError, "entries must yield key/value pairs with #each"
  end

  def each_for_inspect(&)                 = each(&)
  def inspect_pair(inspector, key, value) = inspector.hash_pair(key, value) { inspect_value(inspector, value) }
  def inspect_value(inspector, ...)       = inspector.object(...)
end

#store(key, value) ⇒ BasicObject

Store a value using the map's assignment operation. Concurrent maps override this method to support timeouts.

Parameters:

  • key (BasicObject) —

    the key to store

  • value (BasicObject) —

    the value to store

Returns:

  • (BasicObject) —

    value



165
# File 'lib/farce/abstract/map.rb', line 165

def store(key, value) = self[key] = value

#store_if_absent(key) { ... } ⇒ BasicObject

This method is abstract.

Read an existing value or construct and store a value for an absent key. Existing nil and false values count as present when the implementation permits them. The block runs without holding a map-wide lock. Implementations document their coordination guarantees, ownership requirements, and optional timeout support. A later removal or eviction can cause another call to construct a new value.

Parameters:

  • key (BasicObject) —

    The key to look up or store.

Yields:

  • Called without arguments when the key is absent.

Yield Returns:

  • (BasicObject) —

    The value to store and return.

Returns:

  • (BasicObject) —

    The existing or newly constructed value.

Raises:

  • (LocalJumpError) —

    If no block is given.



155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
# File 'lib/farce/abstract/map.rb', line 155

class Map
  include Internal::MarshalSupport::Map
  include Enumerable
  include Internal::Inspect

  # Store a value using the map's assignment operation.
  # Concurrent maps override this method to support timeouts.
  # @param key [BasicObject] the key to store
  # @param value [BasicObject] the value to store
  # @return [BasicObject] `value`
  def store(key, value) = self[key] = value

  # Return a two-element array containing a key and its associated value, if the key is present,
  # or nil if the key is absent.
  # @param key [BasicObject] The key to look up.
  # @return [Array(BasicObject, BasicObject), nil] A two-element `[key, value]` array, or nil if the key is absent.
  def assoc(key)
    value = fetch(key) { return nil }
    [key, value]
  end

  # (see #compare_keys_by_identity?)
  def compare_by_identity? = compare_keys_by_identity?

  # Implements Ruby's [dig interface](https://docs.ruby-lang.org/en/master/language/dig_methods_rdoc.html).
  # @param key [BasicObject] The key to look up.
  # @param rest [Array<BasicObject>] Additional keys to look up in nested maps.
  # @return [BasicObject, nil] The value found at the nested location, or nil if any key is absent or nil.
  def dig(key, *rest)
    value = self[key]
    return value if rest.empty? || value.nil?
    value.dig(*rest)
  end

  # Returns whether the map contains no entries.
  # @return [Boolean] Whether the map is empty.
  def empty? = size.zero?

  # Return the number of entries currently in the map.
  # @return [Integer]
  def length = size

  # Return whether an observed value matches using this map's value comparison setting.
  # Values are unwrapped before comparison. Concurrent changes may make the result stale.
  # @param value [BasicObject] the value to find
  # @return [Boolean]
  def value?(value)
    identity = compare_values_by_identity?
    each_value.any? { |stored| identity ? stored.equal?(value) : stored == value }
  end
  alias has_value? value?

  # Return a matching key using this map's value comparison setting, or nil.
  # The first observed match is returned. No insertion order is guaranteed.
  # @param value [BasicObject] the value to find
  # @return [BasicObject, nil]
  def key(value)
    pair = rassoc(value)
    pair&.first
  end

  # Return an observed key/value pair using this map's value comparison setting, or nil.
  # Values are unwrapped before comparison. Concurrent changes may make the result stale.
  # @param value [BasicObject] the value to find
  # @return [Array, nil]
  def rassoc(value)
    identity = compare_values_by_identity?
    each_pair do |key, stored|
      return [key, stored] if identity ? stored.equal?(value) : stored == value
    end
    nil
  end

  # Alias for {#key?}
  def has_key?(...) = key?(...) # rubocop:disable Naming/PredicatePrefix
  alias member?  has_key?
  alias include? has_key?

  # Fetches the values associated with multiple keys, using the same missing-key behavior as Hash#fetch.
  # @yield [key] Called for each missing key.
  # @yieldparam key [BasicObject] The missing key.
  # @yieldreturn [BasicObject] The value to return for the missing key.
  # @param keys [Array<BasicObject>] The keys to look up.
  # @return [Array<BasicObject>] An array of the associated values.
  def fetch_values(*keys, &) = keys.map { fetch(it, &) }

  # @note
  #   Some maps may still accept non-shareable keys or values, but convert them into shareable representations.
  #   This method will still return `true` for such maps.
  #
  # @return [Boolean] Whether the map requires keys to be Ractor-shareable
  def shareable_keys? = false

  # @return [Boolean] Whether the map requires values to be Ractor-shareable
  def shareable_values? = false

  # Creates a new Array containing the map's key-value pairs as two-element arrays.
  # @return [Array<Array(BasicObject, BasicObject)>>] A new Array of `[key, value]` arrays.
  def to_a = each_pair.to_a

  # Creates a new Hash containing the map's entries.
  # Preserves identity comparison for keys, including when a block transforms entries.
  # @yieldparam key [BasicObject] an existing key
  # @yieldparam value [BasicObject] its value
  # @yieldreturn [Array(BasicObject, BasicObject)] the key and value for the new Hash
  # @return [Hash] A new Hash with the original entries, or the pairs returned by the block.
  def to_h(&) = entries_to_hash(each_pair, &)

  # Support implicit Hash conversion using this map's {#to_h} implementation.
  # @return [Hash] A new Hash containing the map's entries.
  def to_hash = to_h

  # Support hash patterns using the same entries and key comparison as {#to_h}.
  # Like Hash, this returns all entries regardless of the requested keys.
  # @param keys [Array, nil] the optional key hint supplied by Ruby's pattern matcher
  # @return [Hash] A new Hash containing the map's entries.
  def deconstruct_keys(keys) = to_h # rubocop:disable Lint/UnusedMethodArgument

  # Fetches the values associated with multiple keys, returning nil for any missing keys.
  # @param keys [Array<BasicObject>] The keys to look up.
  # @return [Array<BasicObject>] An array of the associated values, with nil for any missing keys.
  def values_at(*keys) = keys.map { self[it] }

  # Some maps reference their keys weakly, automatically dropping entries when a key gets garbage-collected.
  # @return [Boolean] Whether the map uses weak references for keys.
  def weak_keys? = false

  # Some maps reference their values weakly, automatically dropping entries when a value gets garbage-collected.
  # @return [Boolean] Whether the map uses weak references for values.
  def weak_values? = false

  # @return [String] String representation of the map, suitable for debugging.
  def to_s = inspect

  # @api private
  def inspect_with(inspector)
    super do
      yield if block_given?
      inspector.breakable
      inspector.group("{", "}") do
        inspector.breakable ""
        inspector.seplist(self, nil, :each_for_inspect) do |key, value|
          inspector.group { inspect_pair(inspector, key, value) }
        end
      end
    end
  end

  protected

  # Convert a public value to its stored representation.
  # @api private
  def wrap_value(value) = value

  # Convert a stored representation to its public value.
  # @api private
  def unwrap_value(value) = value

  private

  def entries_to_hash(entries, &)
    return entries.to_h(&) unless compare_keys_by_identity?
    hash = {}.compare_by_identity
    entries.each do |key, value|
      if block_given?
        pair = Array.try_convert(yield(key, value))
        raise TypeError, "block must return an Array or respond to #to_ary" unless pair
        raise ArgumentError, "block must return a two-element pair" unless pair.size == 2
        key, value = pair
      end
      hash[key] = value
    end
    hash
  end

  def convert_entries(entries)
    return entries if Map === entries
    if entries.respond_to?(:to_hash)
      entries = Hash.try_convert(entries)
      raise TypeError, "entries must be a Hash or respond to #to_hash" unless entries
    end
    return entries if entries.nil? || entries.respond_to?(:each)
    raise TypeError, "entries must yield key/value pairs with #each"
  end

  def each_for_inspect(&)                 = each(&)
  def inspect_pair(inspector, key, value) = inspector.hash_pair(key, value) { inspect_value(inspector, value) }
  def inspect_value(inspector, ...)       = inspector.object(...)
end

#to_a ⇒ Array<Array(BasicObject, BasicObject)>

Creates a new Array containing the map's key-value pairs as two-element arrays.

Returns:

  • (Array<Array(BasicObject, BasicObject)>) —

    ] A new Array of [key, value] arrays.



253
# File 'lib/farce/abstract/map.rb', line 253

def to_a = each_pair.to_a

#to_bson(buffer = ::BSON::ByteBuffer.new) ⇒ BSON::ByteBuffer

Note:

This method is only available if BSON has been loaded.

Serialize current entries as a BSON document. Nested value wrappers are read before encoding their BSON types and payloads.

Parameters:

  • buffer (BSON::ByteBuffer) (defaults to: ::BSON::ByteBuffer.new) —

    An optional buffer to append to.

Returns:

  • (BSON::ByteBuffer) —

    The buffer containing the encoded document.



42
# File 'lib/farce/integrations/bson.rb', line 42

def to_bson(buffer = ::BSON::ByteBuffer.new) = to_bson_normalized_value.to_bson(buffer)

#to_bson_normalized_value ⇒ BSON::Document

Note:

This method is only available if BSON has been loaded.

Return current entries with keys and nested values normalized by BSON.

Returns:

  • (BSON::Document) —

    The normalized document.



52
# File 'lib/farce/integrations/bson.rb', line 52

def to_bson_normalized_value = to_h.to_bson_normalized_value

#to_cbor(*arguments) ⇒ String, ...

Note:

This method is only available if CBOR has been loaded.

Note:

On CRuby, CBOR's native encoder must run in the main Ractor.

Serialize current entries as a CBOR map.

Parameters:

  • arguments (Array<Object>) —

    Arguments forwarded to Hash#to_cbor.

Returns:

  • (String, ::CBOR::Packer, nil) —

    Encoded bytes, the supplied packer, or nil when writing to IO.



29
# File 'lib/farce/integrations/cbor.rb', line 29

def to_cbor(...) = to_h.to_cbor(...)

#to_h {|key, value| ... } ⇒ Hash

Creates a new Hash containing the map's entries. Preserves identity comparison for keys, including when a block transforms entries.

Yield Parameters:

  • key (BasicObject) —

    an existing key

  • value (BasicObject) —

    its value

Yield Returns:

  • (Array(BasicObject, BasicObject)) —

    the key and value for the new Hash

Returns:

  • (Hash) —

    A new Hash with the original entries, or the pairs returned by the block.



261
# File 'lib/farce/abstract/map.rb', line 261

def to_h(&) = entries_to_hash(each_pair, &)

#to_hash ⇒ Hash

Support implicit Hash conversion using this map's #to_h implementation.

Returns:

  • (Hash) —

    A new Hash containing the map's entries.



265
# File 'lib/farce/abstract/map.rb', line 265

def to_hash = to_h

#to_json(*arguments) ⇒ String

Note:

This method is only available if a supported JSON library has been loaded.

Serialize current entries as a JSON object.

Returns The generated JSON.

Parameters:

  • arguments (Array<Object>) —

    Arguments forwarded to Hash#to_json.

Returns:

  • (String) —

    The generated JSON.



22
# File 'lib/farce/integrations/shared/to_json.rb', line 22

def to_json(...) = to_h.to_json(...)

#to_msgpack(*arguments) ⇒ String, ::MessagePack::Packer

Note:

This method is only available if MessagePack has been loaded.

Serialize current entries as a MessagePack map.

Parameters:

  • arguments (Array<Object>) —

    Arguments forwarded to Hash#to_msgpack.

Returns:

  • (String, ::MessagePack::Packer) —

    The encoded bytes or supplied packer.



25
# File 'lib/farce/integrations/msgpack.rb', line 25

def to_msgpack(...) = to_h.to_msgpack(...)

#to_query ⇒ String Also known as: to_param

Note:

This methods is only available if ActiveSupport has been loaded.

Encode public entries as a query string, optionally under a namespace.

Returns:

  • (String)


19
# File 'lib/farce/integrations/active_support/map.rb', line 19

def to_query(...) = to_h.to_query(...)

#to_s ⇒ String

Returns String representation of the map, suitable for debugging.

Returns:

  • (String) —

    String representation of the map, suitable for debugging.



287
# File 'lib/farce/abstract/map.rb', line 287

def to_s = inspect

#value?(value) ⇒ Boolean Also known as: has_value?

Return whether an observed value matches using this map's value comparison setting. Values are unwrapped before comparison. Concurrent changes may make the result stale.

Parameters:

  • value (BasicObject) —

    the value to find

Returns:

  • (Boolean)


201
202
203
204
# File 'lib/farce/abstract/map.rb', line 201

def value?(value)
  identity = compare_values_by_identity?
  each_value.any? { |stored| identity ? stored.equal?(value) : stored == value }
end

#values_at(*keys) ⇒ Array<BasicObject>

Fetches the values associated with multiple keys, returning nil for any missing keys.

Parameters:

  • keys (Array<BasicObject>) —

    The keys to look up.

Returns:

  • (Array<BasicObject>) —

    An array of the associated values, with nil for any missing keys.



276
# File 'lib/farce/abstract/map.rb', line 276

def values_at(*keys) = keys.map { self[it] }

#weak_keys? ⇒ Boolean

Some maps reference their keys weakly, automatically dropping entries when a key gets garbage-collected.

Returns:

  • (Boolean) —

    Whether the map uses weak references for keys.



280
# File 'lib/farce/abstract/map.rb', line 280

def weak_keys? = false

#weak_values? ⇒ Boolean

Some maps reference their values weakly, automatically dropping entries when a value gets garbage-collected.

Returns:

  • (Boolean) —

    Whether the map uses weak references for values.



284
# File 'lib/farce/abstract/map.rb', line 284

def weak_values? = false