Class: Erlang::Map

Inherits:
Object
  • Object
show all
Includes:
Associable, Enumerable
Defined in:
lib/erlang/map.rb

Overview

A Erlang::Map maps a set of unique keys to corresponding values, much like a dictionary maps from words to definitions. Given a key, it can store and retrieve an associated value in constant time. If an existing key is stored again, the new value will replace the old. It behaves much like Ruby's built-in Hash, which we will call RubyHash for clarity. Like RubyHash, two keys that are #eql? to each other and have the same #hash are considered identical in a Erlang::Map.

A Erlang::Map can be created in a couple of ways:

Erlang::Map[first_name: 'John', last_name: 'Smith']
Erlang::Map[:first_name, 'John', :last_name, 'Smith']

Any Enumerable object with an even number of elements can be used to initialize a Erlang::Map:

Erlang::Map[:first_name, 'John', :last_name, 'Smith']

Any Enumerable object which yields two-element [key, value] arrays can be used to initialize a Erlang::Map:

Erlang::Map.new([[:first_name, 'John'], [:last_name, 'Smith']])

Key/value pairs can be added using #put. A new map is returned and the existing one is left unchanged:

map = Erlang::Map[a: 100, b: 200]
map.put(:c, 500) # => Erlang::Map[:a => 100, :b => 200, :c => 500]
map              # => Erlang::Map[:a => 100, :b => 200]

#put can also take a block, which is used to calculate the value to be stored.

map.put(:a) { |current| current + 200 } # => Erlang::Map[:a => 300, :b => 200]

Since it is immutable, all methods which you might expect to "modify" a Erlang::Map actually return a new map and leave the existing one unchanged. This means that the map[key] = value syntax from RubyHash cannot be used with Erlang::Map.

Nested data structures can easily be updated using #update_in:

map = Erlang::Map["a" => Erlang::Tuple[Erlang::Map["c" => 42]]]
map.update_in("a", 0, "c") { |value| value + 5 }
# => Erlang::Map["a" => Erlang::Tuple[Erlang::Map["c" => 47]]]

While a Erlang::Map can iterate over its keys or values, it does not guarantee any specific iteration order (unlike RubyHash). Methods like #flatten do not guarantee the order of returned key/value pairs.

Like RubyHash, a Erlang::Map can have a default block which is used when looking up a key that does not exist. Unlike RubyHash, the default block will only be passed the missing key, without the hash itself:

map = Erlang::Map.new { |missing_key| missing_key * 10 }
map[5] # => 50

Licensing

Portions taken and modified from https://github.com/hamstergem/hamster

Copyright (c) 2009-2014 Simon Harris

Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Associable

#dig

Methods included from Enumerable

#compact, #each_index, #grep, #grep_v, #group_by, #join, #partition, #product, #reject, #sum

Constructor Details

#initialize(pairs = nil) {|key| ... } ⇒ Map

Returns a new instance of Map.

Parameters:

  • pairs (::Enumerable) (defaults to: nil)

    initial content of map. An empty map is returned if not provided.

Yields:

  • (key)

    Optional default block to be stored and used to calculate the default value of a missing key. It will not be yielded during this method. It will not be preserved when marshalling.

Yield Parameters:

  • key

    Key that was not present in the map.



149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
# File 'lib/erlang/map.rb', line 149

def initialize(pairs = nil, &block)
  if pairs
    obj = ::Array.new(pairs.size)
    i = 0
    pairs.each do |key, val|
      obj[i] = [Erlang.from(key), Erlang.from(val)]
      i += 1
    end
    pairs = obj
  end
  @trie = pairs ? Trie[pairs] : EmptyTrie
  @default = block
  if block_given?
    @default = ->(key) {
      return Erlang.from(block.call(key))
    }
  end
end

Class Method Details

.[](*pairs) ⇒ Map

Create a new Map populated with the given key/value pairs.

Examples:

Erlang::Map["A" => 1, "B" => 2] # => Erlang::Map["A" => 1, "B" => 2]
Erlang::Map["A", 1, "B", 2] # => Erlang::Map["A" => 1, "B" => 2]

Parameters:

  • pairs (::Enumerable)

    initial content of hash. An empty hash is returned if not provided.

Returns:

Raises:

  • (ArgumentError)


105
106
107
108
109
110
111
112
113
114
# File 'lib/erlang/map.rb', line 105

def [](*pairs)
  return empty if pairs.nil? or pairs.empty?
  if pairs.size == 1
    return pairs[0] if pairs[0].is_a?(Erlang::Map)
    return new(pairs[0]) if pairs[0].is_a?(::Hash)
  end
  raise ArgumentError, 'odd number of arguments for Erlang::Map' if pairs.size.odd?
  pairs = pairs.each_slice(2).to_a
  return new(pairs)
end

.compare(a, b) ⇒ Object

Raises:

  • (ArgumentError)


136
137
138
139
140
141
142
143
# File 'lib/erlang/map.rb', line 136

def compare(a, b)
  raise ArgumentError, "'a' must be of Erlang::Map type" if not a.kind_of?(Erlang::Map)
  raise ArgumentError, "'b' must be of Erlang::Map type" if not b.kind_of?(Erlang::Map)
  c = a.size <=> b.size
  return c if c != 0
  return 0 if a.eql?(b)
  return Erlang.compare(a.sort, b.sort)
end

.emptyMap

Return an empty Map. If used on a subclass, returns an empty instance of that class.

Returns:



120
121
122
# File 'lib/erlang/map.rb', line 120

def empty
  return @empty ||= self.new
end

Instance Method Details

#assoc(obj) ⇒ Tuple

Searches through the Map, comparing obj with each key (using #==). When a matching key is found, return the [key, value] pair as a Tuple. Return nil if no match is found.

Examples:

Erlang::Map["A" => 1, "B" => 2, "C" => 3].assoc("B")  # => Erlang::Tuple["B", 2]

Parameters:

  • obj (Object)

    The key to search for (using #==)

Returns:



742
743
744
745
746
# File 'lib/erlang/map.rb', line 742

def assoc(obj)
  obj = Erlang.from(obj)
  each { |entry| return Erlang::Tuple[*entry] if obj == entry[0] }
  return nil
end

#clearMap

Return an empty Map instance, of the same class as this one. Useful if you have multiple subclasses of Map and want to treat them polymorphically. Maintains the default block, if there is one.

Returns:



795
796
797
798
799
800
801
# File 'lib/erlang/map.rb', line 795

def clear
  if @default
    return self.class.alloc(EmptyTrie, @default)
  else
    return self.class.empty
  end
end

#default_procProc

Return the default block if there is one. Otherwise, return nil.

Returns:

  • (Proc)


171
172
173
# File 'lib/erlang/map.rb', line 171

def default_proc
  return @default
end

#delete(key) ⇒ Map

Return a new Map with key removed. If key is not present, return self.

Examples:

Erlang::Map["A" => 1, "B" => 2, "C" => 3].delete("B")
# => Erlang::Map["A" => 1, "C" => 3]

Parameters:

  • key (Object)

    The key to remove

Returns:



378
379
380
# File 'lib/erlang/map.rb', line 378

def delete(key)
  return derive_new_map(@trie.delete(key))
end

#each {|key, value| ... } ⇒ self Also known as: each_pair

Call the block once for each key/value pair in this Map, passing the key/value pair as parameters. No specific iteration order is guaranteed, though the order will be stable for any particular Map.

Examples:

Erlang::Map["A" => 1, "B" => 2, "C" => 3].each { |k, v| puts "k=#{k} v=#{v}" }

k=A v=1
k=C v=3
k=B v=2
# => Erlang::Map["A" => 1, "B" => 2, "C" => 3]

Yields:

  • (key, value)

    Once for each key/value pair.

Returns:

  • (self)


396
397
398
399
400
# File 'lib/erlang/map.rb', line 396

def each(&block)
  return to_enum if not block_given?
  @trie.each(&block)
  return self
end

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

Call the block once for each key/value pair in this Map, passing the key as a parameter. Ordering guarantees are the same as #each.

Examples:

Erlang::Map["A" => 1, "B" => 2, "C" => 3].each_key { |k| puts "k=#{k}" }

k=A
k=C
k=B
# => Erlang::Map["A" => 1, "B" => 2, "C" => 3]

Yields:

  • (key)

    Once for each key/value pair.

Returns:

  • (self)


435
436
437
438
439
# File 'lib/erlang/map.rb', line 435

def each_key
  return enum_for(:each_key) if not block_given?
  @trie.each { |k,v| yield k }
  return self
end

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

Call the block once for each key/value pair in this Map, passing the value as a parameter. Ordering guarantees are the same as #each.

Examples:

Erlang::Map["A" => 1, "B" => 2, "C" => 3].each_value { |v| puts "v=#{v}" }

v=1
v=3
v=2
# => Erlang::Map["A" => 1, "B" => 2, "C" => 3]

Yields:

  • (value)

    Once for each key/value pair.

Returns:

  • (self)


454
455
456
457
458
# File 'lib/erlang/map.rb', line 454

def each_value
  return enum_for(:each_value) if not block_given?
  @trie.each { |k,v| yield v }
  return self
end

#empty?Boolean

Return true if this Map contains no key/value pairs.

Returns:

  • (Boolean)


190
191
192
# File 'lib/erlang/map.rb', line 190

def empty?
  return @trie.empty?
end

#eql?(other) ⇒ Boolean Also known as: ==

Return true if other has the same type and contents as this Map.

Parameters:

  • other (Object)

    The collection to compare with

Returns:

  • (Boolean)


807
808
809
810
811
# File 'lib/erlang/map.rb', line 807

def eql?(other)
  return true if other.equal?(self)
  return @trie.eql?(other.instance_variable_get(:@trie)) if instance_of?(other.class)
  return !!(Erlang.compare(other, self) == 0)
end

#erlang_inspect(raw = false) ⇒ String

Allows this Map to be printed using Erlang.inspect().

Returns:



843
844
845
846
847
848
849
850
851
852
# File 'lib/erlang/map.rb', line 843

def erlang_inspect(raw = false)
  result = '#{'
  each_with_index do |(key, val), i|
    result << ',' if i > 0
    result << Erlang.inspect(key, raw: raw)
    result << ' => '
    result << Erlang.inspect(val, raw: raw)
  end
  return result << '}'
end

#except(*keys) ⇒ Map

Return a new Map with the associations for all of the given keys removed.

Examples:

m = Erlang::Map["A" => 1, "B" => 2, "C" => 3]
m.except("A", "C")  # => Erlang::Map["B" => 2]

Parameters:

  • keys (Array)

    The keys to remove

Returns:



609
610
611
# File 'lib/erlang/map.rb', line 609

def except(*keys)
  return keys.reduce(self) { |map, key| map.delete(key) }
end

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

Retrieve the value corresponding to the given key object, or use the provided default value or block, or otherwise raise a KeyError.

Examples:

m = Erlang::Map["A" => 1, "B" => 2, "C" => 3]
m.fetch("B")         # => 2
m.fetch("Elephant")  # => KeyError: key not found: "Elephant"

# with a default value:
m.fetch("B", 99)         # => 2
m.fetch("Elephant", 99)  # => 99

# with a block:
m.fetch("B") { |key| key.size }         # => 2
m.fetch("Elephant") { |key| key.size }  # => 8

Overloads:

  • #fetch(key) ⇒ Object

    Retrieve the value corresponding to the given key, or raise a KeyError if it is not found.

    Parameters:

    • key (Object)

      The key to look up

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

    Retrieve the value corresponding to the given key, or call the optional code block (with the missing key) and get its return value.

    Parameters:

    • key (Object)

      The key to look up

    Yields:

    • (key)

      The key which was not found

    Yield Returns:

    • (Object)

      Object to return since the key was not found

  • #fetch(key, default) ⇒ Object

    Retrieve the value corresponding to the given key, or else return the provided default value.

    Parameters:

    • key (Object)

      The key to look up

    • default (Object)

      Object to return if the key is not found

Returns:

  • (Object)


286
287
288
289
290
291
292
293
294
295
296
297
298
# File 'lib/erlang/map.rb', line 286

def fetch(key, default = Undefined)
  key = Erlang.from(key)
  entry = @trie.get(key)
  if entry
    return entry[1]
  elsif block_given?
    return yield(key)
  elsif not Undefined.equal?(default)
    return Erlang.from(default)
  else
    raise KeyError, "key not found: #{key.inspect}"
  end
end

#fetch_values(*wanted) ⇒ Tuple

Return a List of the values which correspond to the wanted keys. If any of the wanted keys are not present in this Map, raise KeyError exception.

Examples:

m = Erlang::Map["A" => 1, "B" => 2, "C" => 3]
m.fetch_values("C", "A")  # => Erlang::List[3, 1]
m.fetch_values("C", "Z")  # => KeyError: key not found: "Z"

Parameters:

  • wanted (Array)

    The keys to retrieve

Returns:



660
661
662
663
664
665
666
# File 'lib/erlang/map.rb', line 660

def fetch_values(*wanted)
  array = wanted.map { |key|
    key = Erlang.from(key)
    fetch(key)
  }
  return List.from_enum(array.freeze)
end

#find {|key, value| ... } ⇒ Array Also known as: detect

Yield [key, value] pairs until one is found for which the block returns true. Return that [key, value] pair. If the block never returns true, return nil.

Examples:

m = Erlang::Map["A" => 1, "B" => 2, "C" => 3]
m.find { |k, v| v.even? }
# => ["B", 2]

Yields:

  • (key, value)

    At most once for each key/value pair, until the block returns true.

Yield Returns:

  • Truthy to halt iteration and return the yielded key/value pair.

Returns:

  • (Array)


506
507
508
509
510
# File 'lib/erlang/map.rb', line 506

def find
  return enum_for(:find) unless block_given?
  each { |entry| return entry if yield entry }
  return nil
end

#flatten(level = 1) ⇒ List

Return a new List which is a one-dimensional flattening of this Map. If level is 1, all the [key, value] pairs in the hash will be concatenated into one List. If level is greater than 1, keys or values which are themselves Arrays or Lists will be recursively flattened into the output List. The depth to which that flattening will be recursively applied is determined by level.

As a special case, if level is 0, each [key, value] pair will be a separate element in the returned List.

Examples:

m = Erlang::Map["A" => 1, "B" => [2, 3, 4]]
m.flatten
# => Erlang::List["A", 1, "B", [2, 3, 4]]
h.flatten(2)
# => Erlang::List["A", 1, "B", 2, 3, 4]

Parameters:

  • level (Integer) (defaults to: 1)

    The number of times to recursively flatten the [key, value] pairs in this Map.

Returns:



725
726
727
728
729
730
731
# File 'lib/erlang/map.rb', line 725

def flatten(level = 1)
  return List.from_enum(self) if level == 0
  array = []
  each { |k,v| array << k; array << v }
  array.flatten!(level-1) if level > 1
  return List.from_enum(array.freeze)
end

#get(key) ⇒ Object Also known as: []

Retrieve the value corresponding to the provided key object. If not found, and this Map has a default block, the default block is called to provide the value. Otherwise, return nil.

Examples:

m = Erlang::Map["A" => 1, "B" => 2, "C" => 3]
m["B"]             # => 2
m.get("B")         # => 2
m.get("Elephant")  # => nil

# Erlang Map with a default proc:
m = Erlang::Map.new("A" => 1, "B" => 2, "C" => 3) { |key| key.size }
m.get("B")         # => 2
m.get("Elephant")  # => 8

Parameters:

  • key (Object)

    The key to look up

Returns:

  • (Object)


242
243
244
245
246
247
248
249
250
# File 'lib/erlang/map.rb', line 242

def get(key)
  key = Erlang.from(key)
  entry = @trie.get(key)
  if entry
    return entry[1]
  elsif @default
    return @default.call(key)
  end
end

#hashInteger

See Object#hash.

Returns:

  • (Integer)


816
817
818
819
820
# File 'lib/erlang/map.rb', line 816

def hash
  return keys.sort.reduce(Erlang::Map.hash) do |acc, key|
    (acc << 32) - acc + key.hash + get(key).hash
  end
end

#inspectString

Return the contents of this Map as a programmer-readable String. If all the keys and values are serializable as Ruby literal strings, the returned string can be passed to eval to reconstitute an equivalent Map. The default block (if there is one) will be lost when doing this, however.

Returns:



828
829
830
831
832
833
834
835
836
837
838
# File 'lib/erlang/map.rb', line 828

def inspect
  # result = "#{self.class}["
  result = "{"
  i = 0
  each do |key, val|
    result << ', ' if i > 0
    result << key.inspect << ' => ' << val.inspect
    i += 1
  end
  return result << "}"
end

#invertMap

Return a new Map created by using keys as values and values as keys. If there are multiple values which are equivalent (as determined by #hash and #eql?), only one out of each group of equivalent values will be retained. Which one specifically is undefined.

Examples:

Erlang::Map["A" => 1, "B" => 2, "C" => 3, "D" => 2].invert
# => Erlang::Map[1 => "A", 3 => "C", 2 => "B"]

Returns:



700
701
702
703
704
# File 'lib/erlang/map.rb', line 700

def invert
  pairs = []
  each { |k,v| pairs << [v, k] }
  return self.class.new(pairs, &@default)
end

#key(value) ⇒ Object

Searches through the Map, comparing value with each value (using #==). When a matching value is found, return its associated key object. Return nil if no match is found.

Examples:

Erlang::Map["A" => 1, "B" => 2, "C" => 3].key(2)  # => "B"

Parameters:

  • value (Object)

    The value to search for (using #==)

Returns:

  • (Object)


772
773
774
775
776
# File 'lib/erlang/map.rb', line 772

def key(value)
  value = Erlang.from(value)
  each { |entry| return entry[0] if value == entry[1] }
  return nil
end

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

Return true if the given key object is present in this Map. More precisely, return true if a key with the same #hash code, and which is also #eql? to the given key object is present.

Examples:

Erlang::Map["A" => 1, "B" => 2, "C" => 3].key?("B")  # => true

Parameters:

  • key (Object)

    The key to check for

Returns:

  • (Boolean)


203
204
205
206
# File 'lib/erlang/map.rb', line 203

def key?(key)
  key = Erlang.from(key)
  return @trie.key?(key)
end

#keysSet

Return a new List containing the keys from this Map.

Examples:

Erlang::Map["A" => 1, "B" => 2, "C" => 3, "D" => 2].keys
# => Erlang::List["D", "C", "B", "A"]

Returns:

  • (Set)


675
676
677
# File 'lib/erlang/map.rb', line 675

def keys
  return Erlang::List.from_enum(each_key.to_a.freeze)
end

#map {|key, value| ... } ⇒ Map Also known as: collect

Call the block once for each key/value pair in this Map, passing the key/value pair as parameters. The block should return a [key, value] array each time. All the returned [key, value] arrays will be gathered into a new Map.

Examples:

m = Erlang::Map["A" => 1, "B" => 2, "C" => 3]
m.map { |k, v| ["new-#{k}", v * v] }
# => Erlang::Map["new-C" => 9, "new-B" => 4, "new-A" => 1]

Yields:

  • (key, value)

    Once for each key/value pair.

Returns:



471
472
473
474
475
# File 'lib/erlang/map.rb', line 471

def map
  return enum_for(:map) unless block_given?
  return self if empty?
  return self.class.new(super, &@default)
end

#merge(other) {|key, my_value, other_value| ... } ⇒ Map

Return a new Map containing all the key/value pairs from this Map and other. If no block is provided, the value for entries with colliding keys will be that from other. Otherwise, the value for each duplicate key is determined by calling the block.

other can be a Erlang::Map, a built-in Ruby Map, or any Enumerable object which yields [key, value] pairs.

Examples:

m1 = Erlang::Map["A" => 1, "B" => 2, "C" => 3]
m2 = Erlang::Map["C" => 70, "D" => 80]
m1.merge(m2)
# => Erlang::Map["C" => 70, "A" => 1, "D" => 80, "B" => 2]
m1.merge(m2) { |key, v1, v2| v1 + v2 }
# => Erlang::Map["C" => 73, "A" => 1, "D" => 80, "B" => 2]

Parameters:

  • other (::Enumerable)

    The collection to merge with

Yield Parameters:

  • key (Object)

    The key which was present in both collections

  • my_value (Object)

    The associated value from this Map

  • other_value (Object)

    The associated value from the other collection

Yield Returns:

  • (Object)

    The value to associate this key with in the new Map

Returns:



535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
# File 'lib/erlang/map.rb', line 535

def merge(other)
  other = Erlang.from(other)
  trie = if block_given?
    other.reduce(@trie) do |acc, (key, value)|
      if entry = acc.get(key)
        acc.put(key, yield(key, entry[1], value))
      else
        acc.put(key, value)
      end
    end
  else
    @trie.bulk_put(other)
  end

  return derive_new_map(trie)
end

#put(key, value = yield(get(key))) {|value| ... } ⇒ Map

Return a new Map with the existing key/value associations, plus an association between the provided key and value. If an equivalent key is already present, its associated value will be replaced with the provided one.

If the value argument is missing, but an optional code block is provided, it will be passed the existing value (or nil if there is none) and what it returns will replace the existing value. This is useful for "transforming" the value associated with a certain key.

Avoid mutating objects which are used as keys. Strings are an exception: unfrozen Strings which are used as keys are internally duplicated and frozen. This matches RubyHash's behaviour.

Examples:

m = Erlang::Map["A" => 1, "B" => 2]
m.put("C", 3)
# => Erlang::Map["A" => 1, "B" => 2, "C" => 3]
m.put("B") { |value| value * 10 }
# => Erlang::Map["A" => 1, "B" => 20]

Parameters:

  • key (Object)

    The key to store

  • value (Object) (defaults to: yield(get(key)))

    The value to associate it with

Yields:

  • (value)

    The previously stored value, or nil if none.

Yield Returns:

  • (Object)

    The new value to store

Returns:



325
326
327
328
329
330
331
332
# File 'lib/erlang/map.rb', line 325

def put(key, value = yield(get(key)))
  new_trie = @trie.put(Erlang.from(key), Erlang.from(value))
  if new_trie.equal?(@trie)
    return self
  else
    return self.class.alloc(new_trie, @default)
  end
end

#rassoc(obj) ⇒ Tuple

Searches through the Map, comparing obj with each value (using #==). When a matching value is found, return the [key, value] pair as a Tuple. Return nil if no match is found.

Examples:

Erlang::Map["A" => 1, "B" => 2, "C" => 3].rassoc(2)  # => Erlang::Tuple["B", 2]

Parameters:

  • obj (Object)

    The value to search for (using #==)

Returns:



757
758
759
760
761
# File 'lib/erlang/map.rb', line 757

def rassoc(obj)
  obj = Erlang.from(obj)
  each { |entry| return Erlang::Tuple[*entry] if obj == entry[1] }
  return nil
end

#reverse_each {|key, value| ... } ⇒ self

Call the block once for each key/value pair in this Map, passing the key/value pair as parameters. Iteration order will be the opposite of #each.

Examples:

Erlang::Map["A" => 1, "B" => 2, "C" => 3].reverse_each { |k, v| puts "k=#{k} v=#{v}" }

k=B v=2
k=C v=3
k=A v=1
# => Erlang::Map["A" => 1, "B" => 2, "C" => 3]

Yields:

  • (key, value)

    Once for each key/value pair.

Returns:

  • (self)


416
417
418
419
420
# File 'lib/erlang/map.rb', line 416

def reverse_each(&block)
  return enum_for(:reverse_each) if not block_given?
  @trie.reverse_each(&block)
  return self
end

#sampleTuple

Return a randomly chosen [key, value] pair from this Map. If the hash is empty, return nil.

Examples:

Erlang::Map["A" => 1, "B" => 2, "C" => 3].sample
# => Erlang::Tuple["C", 3]

Returns:



786
787
788
# File 'lib/erlang/map.rb', line 786

def sample
  return Erlang::Tuple[*@trie.at(rand(size))]
end

#select {|key, value| ... } ⇒ Map Also known as: find_all, keep_if

Return a new Map with all the key/value pairs for which the block returns true.

Examples:

m = Erlang::Map["A" => 1, "B" => 2, "C" => 3]
m.select { |k, v| v >= 2 }
# => Erlang::Map["B" => 2, "C" => 3]

Yields:

  • (key, value)

    Once for each key/value pair.

Yield Returns:

  • Truthy if this pair should be present in the new Map.

Returns:



488
489
490
491
# File 'lib/erlang/map.rb', line 488

def select(&block)
  return enum_for(:select) unless block_given?
  return derive_new_map(@trie.select(&block))
end

#slice(*wanted) ⇒ Map

Return a new Map with only the associations for the wanted keys retained.

Examples:

m = Erlang::Map["A" => 1, "B" => 2, "C" => 3]
m.slice("B", "C")  # => Erlang::Map["B" => 2, "C" => 3]

Parameters:

  • wanted (::Enumerable)

    The keys to retain

Returns:



621
622
623
624
625
626
627
628
# File 'lib/erlang/map.rb', line 621

def slice(*wanted)
  trie = Trie.new(0)
  wanted.each { |key|
    key = Erlang.from(key)
    trie.put!(key, get(key)) if key?(key)
  }
  return self.class.alloc(trie, @default)
end

#sortList #sort({ |(k1, v1), (k2, v2)| ... }) {|(k1, v1), (k2, v2)| ... } ⇒ List

Return a sorted List which contains all the [key, value] pairs in this Map as two-element Tuples.

Overloads:

  • #sortList

    Uses #<=> to determine sorted order.

  • #sort({ |(k1, v1), (k2, v2)| ... }) {|(k1, v1), (k2, v2)| ... } ⇒ List

    Uses the block as a comparator to determine sorted order.

    Examples:

    m = Erlang::Map["Dog" => 1, "Elephant" => 2, "Lion" => 3]
    m.sort { |(k1, v1), (k2, v2)| k1.size  <=> k2.size }
    # => Erlang::List[Erlang::Tuple["Dog", 1], Erlang::Tuple["Lion", 3], Erlang::Tuple["Elephant", 2]]

    Yields:

    • ((k1, v1), (k2, v2))

      Any number of times with different pairs of key/value associations.

    Yield Returns:

    • (Integer)

      Negative if the first pair should be sorted lower, positive if the latter pair, or 0 if equal.

Returns:

See Also:

  • Enumerable#sort


571
572
573
574
575
576
# File 'lib/erlang/map.rb', line 571

def sort(&comparator)
  comparator = Erlang.method(:compare) unless block_given?
  array = super(&comparator)
  array.map! { |k, v| next Erlang::Tuple[k, v] }
  return List.from_enum(array)
end

#sort_by {|key, value| ... } ⇒ List

Return a List which contains all the [key, value] pairs in this Hash as two-element Tuples. The order which the pairs will appear in is determined by passing each pair to the code block to obtain a sort key object, and comparing the sort keys using #<=>.

Examples:

m = Erlang::Map["Dog" => 1, "Elephant" => 2, "Lion" => 3]
m.sort_by { |key, value| key.size }
# => Erlang::List[Erlang::Tuple["Dog", 1], Erlang::Tuple["Lion", 3], Erlang::Tuple["Elephant", 2]]

Yields:

  • (key, value)

    Once for each key/value pair.

Yield Returns:

  • a sort key object for the yielded pair.

Returns:

See Also:

  • Enumerable#sort_by


593
594
595
596
597
598
599
# File 'lib/erlang/map.rb', line 593

def sort_by(&transformer)
  return sort unless block_given?
  block = ->(x) { Erlang.from(transformer.call(x)) }
  array = super(&block)
  array.map! { |k, v| next Erlang::Tuple[k, v] }
  return List.from_enum(array)
end

#store(key, value) ⇒ Map

An alias for #put to match RubyHash's API. Does not support #put's block form.

Parameters:

  • key (Object)

    The key to store

  • value (Object)

    The value to associate it with

Returns:

See Also:



365
366
367
# File 'lib/erlang/map.rb', line 365

def store(key, value)
  return put(key, value)
end

#to_hash::Hash Also known as: to_h

Convert this Erlang::Map to an instance of Ruby's built-in Hash.

Returns:

  • (::Hash)


880
881
882
883
884
885
886
# File 'lib/erlang/map.rb', line 880

def to_hash
  output = {}
  each do |key, value|
    output[key] = value
  end
  return output
end

#to_procProc

Return a Proc which accepts a key as an argument and returns the value. The Proc behaves like #get (when the key is missing, it returns nil or result of the default proc).

Examples:

m = Erlang::Map["A" => 1, "B" => 2, "C" => 3]
m.to_proc.call("B")
# => 2
["A", "C", "X"].map(&h)   # The & is short for .to_proc in Ruby
# => [1, 3, nil]

Returns:

  • (Proc)


901
902
903
# File 'lib/erlang/map.rb', line 901

def to_proc
  return lambda { |key| get(key) }
end

#update_in(*key_path) {|value| ... } ⇒ Map

Return a new Map with a deeply nested value modified to the result of the given code block. When traversing the nested Mapes and Tuples, non-existing keys are created with empty Map values.

The code block receives the existing value of the deeply nested key (or nil if it doesn't exist). This is useful for "transforming" the value associated with a certain key.

Note that the original Map and sub-Mapes and sub-Tuples are left unmodified; new data structure copies are created along the path wherever needed.

Examples:

map = Erlang::Map["a" => Erlang::Map["b" => Erlang::Map["c" => 42]]]
map.update_in("a", "b", "c") { |value| value + 5 }
# => Erlang::Map["a" => Erlang::Map["b" => Erlang::Map["c" => 47]]]

Parameters:

  • key_path (::Array<Object>)

    List of keys which form the path to the key to be modified

Yields:

  • (value)

    The previously stored value

Yield Returns:

  • (Object)

    The new value to store

Returns:

See Also:



# File 'lib/erlang/map.rb', line 334

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

Return true if this Map has one or more keys which map to the provided value.

Examples:

Erlang::Map["A" => 1, "B" => 2, "C" => 3].value?(2)  # => true

Parameters:

  • value (Object)

    The value to check for

Returns:

  • (Boolean)


218
219
220
221
222
# File 'lib/erlang/map.rb', line 218

def value?(value)
  value = Erlang.from(value)
  each { |k,v| return true if value == v }
  return false
end

#valuesList

Return a new List populated with the values from this Map.

Examples:

Erlang::Map["A" => 1, "B" => 2, "C" => 3, "D" => 2].values
# => Erlang::List[2, 3, 2, 1]

Returns:



686
687
688
# File 'lib/erlang/map.rb', line 686

def values
  return Erlang::List.from_enum(each_value.to_a.freeze)
end

#values_at(*wanted) ⇒ List

Return a List of the values which correspond to the wanted keys. If any of the wanted keys are not present in this Map, nil will be placed instead, or the result of the default proc (if one is defined), similar to the behavior of #get.

Examples:

m = Erlang::Map["A" => 1, "B" => 2, "C" => 3]
m.values_at("B", "A", "D")  # => Erlang::List[2, 1, nil]

Parameters:

  • wanted (Array)

    The keys to retrieve

Returns:



641
642
643
644
645
646
647
# File 'lib/erlang/map.rb', line 641

def values_at(*wanted)
  array = wanted.map { |key|
    key = Erlang.from(key)
    get(key)
  }
  return List.from_enum(array.freeze)
end