Module: Hamster

Defined in:
lib/hamster/set.rb,
lib/hamster/hash.rb,
lib/hamster/list.rb,
lib/hamster/trie.rb,
lib/hamster/deque.rb,
lib/hamster/nested.rb,
lib/hamster/vector.rb,
lib/hamster/version.rb,
lib/hamster/immutable.rb,
lib/hamster/undefined.rb,
lib/hamster/enumerable.rb,
lib/hamster/sorted_set.rb,
lib/hamster/mutable_hash.rb,
lib/hamster/read_copy_update.rb,
lib/hamster/experimental/mutable_set.rb,
lib/hamster/experimental/mutable_queue.rb

Defined Under Namespace

Modules: EmptyList, Enumerable, List Classes: Deque, Hash, MutableHash, MutableQueue, MutableSet, Set, SortedSet, Vector

Constant Summary collapse

EmptySet =

The canonical empty Set. Returned by Hamster.set and Set[] when invoked with no arguments; also returned by Set.empty. Prefer using this one rather than creating many empty sets using Set.new.

Hamster::Set.empty
EmptyHash =

The canonical empty Hash. Returned by Hamster.hash and Hash[] when invoked with no arguments; also returned by Hash.empty. Prefer using this one rather than creating many empty hashes using Hash.new.

Hamster::Hash.empty
EmptyDeque =

The canonical empty Deque. Returned by Hamster.deque and Deque[] when invoked with no arguments; also returned by Deque.empty. Prefer using this one rather than creating many empty deques using Deque.new.

Hamster::Deque.empty
EmptyVector =

The canonical empty Vector. Returned by Hamster.vector and Vector[] when invoked with no arguments; also returned by Vector.empty. Prefer using this one rather than creating many empty vectors using Vector.new.

Hamster::Vector.empty
VERSION =
"1.0.0"
EmptySortedSet =

The canonical empty SortedSet. Returned by Hamster.sorted_set and SortedSet[] when invoked with no arguments; also returned by SortedSet.empty. Prefer using this one rather than creating many empty sorted sets using SortedSet.new.

Hamster::SortedSet.empty

Class Method Summary collapse

Class Method Details

.deque(*items) ⇒ Deque

Create a new Deque populated with the given items.

Returns:


7
8
9
# File 'lib/hamster/deque.rb', line 7

def self.deque(*items)
  items.empty? ? EmptyDeque : Deque.new(items)
end

.enumerate(enum) ⇒ List

Turn an Enumerator into a Hamster::List. The result is a lazy collection where the values are memoized as they are generated.

If your code uses multiple threads, you need to make sure that the returned lazy collection is realized on a single thread only. Otherwise, a FiberError will be raised. After the collection is realized, it can be used from other threads as well.

Examples:

def rg; loop { yield rand(100) }; end
Hamster.enumerate(to_enum(:rg)).take(10)

Parameters:

  • enum (Enumerator)

    The object to iterate over

Returns:


104
105
106
107
108
109
110
111
112
# File 'lib/hamster/list.rb', line 104

def enumerate(enum)
  LazyList.new do
    begin
      Cons.new(enum.next, enumerate(enum))
    rescue StopIteration
      EmptyList
    end
  end
end

.from(obj) ⇒ Hamster::Hash, ...

Create a Hamster immutable data structure with nested Hamster data structure from a nested Ruby object obj. This method recursively "walks" the Ruby object, converting Ruby Hash to Hamster::Hash, Ruby Array to Hamster::Vector and Ruby Set to Hamster::Set. Other Ruby objects are left as-is.

Examples:

h = Hamster.from({ "a" => [1, 2], "b" => "c" })
# => Hamster::Hash["a" => Hamster::Vector[1, 2], "b" => "c"]

Returns:


21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
# File 'lib/hamster/nested.rb', line 21

def from(obj)
  case obj
  when ::Hash
    res = obj.map { |key, value| [from(key), from(value)] }
    Hamster::Hash.new(res)
  when Hamster::Hash
    obj.map { |key, value| [from(key), from(value)] }
  when ::Array
    res = obj.map { |element| from(element) }
    Hamster::Vector.new(res)
  when ::SortedSet
    # This clause must go before ::Set clause, since ::SortedSet is a ::Set.
    res = obj.map { |element| from(element) }
    Hamster::SortedSet.new(res)
  when ::Set
    res = obj.map { |element| from(element) }
    Hamster::Set.new(res)
  when Hamster::Vector, Hamster::Set, Hamster::SortedSet
    obj.map { |element| from(element) }
  else
    obj
  end
end

.hash(pairs = nil, &block) ⇒ Object


10
11
12
# File 'lib/hamster/hash.rb', line 10

def self.hash(pairs = nil, &block)
  (pairs.nil? && block.nil?) ? EmptyHash : Hash.new(pairs, &block)
end

.interval(from, to) ⇒ List

Construct a list of consecutive integers.

Examples:

Hamster.interval(5,9)
# => Hamster::List[5, 6, 7, 8, 9]

Parameters:

  • from (Integer)

    Start value, inclusive

  • to (Integer)

    End value, inclusive

Returns:


48
49
50
51
# File 'lib/hamster/list.rb', line 48

def interval(from, to)
  return EmptyList if from > to
  interval_exclusive(from, to.next)
end

.iterate(item) {|The| ... } ⇒ List

Create an infinite list where each item is derived from the previous one, using the provided block

Examples:

Hamster.iterate(0) { |i| i.next }.take(5)
# => Hamster::List[0, 1, 2, 3, 4]

Parameters:

  • item (Object)

    Starting value

Yield Parameters:

  • The (Object)

    previous value

Yield Returns:

  • (Object)

    The next value

Returns:


86
87
88
# File 'lib/hamster/list.rb', line 86

def iterate(item, &block)
  LazyList.new { Cons.new(item, iterate(yield(item), &block)) }
end

.list(*items) ⇒ List

Create a list containing the given items.

Examples:

list = Hamster.list(:a, :b, :c)
# => Hamster::List[:a, :b, :c]

Returns:


21
22
23
# File 'lib/hamster/list.rb', line 21

def list(*items)
  items.to_list
end

.mutable_hash(pairs = {}, &block) ⇒ Object


5
6
7
# File 'lib/hamster/mutable_hash.rb', line 5

def self.mutable_hash(pairs = {}, &block)
  MutableHash.new(hash(pairs, &block))
end

.mutable_queue(*items) ⇒ Object


5
6
7
# File 'lib/hamster/experimental/mutable_queue.rb', line 5

def self.mutable_queue(*items)
  MutableQueue.new(deque(*items))
end

.mutable_set(*items) ⇒ Object


5
6
7
# File 'lib/hamster/experimental/mutable_set.rb', line 5

def self.mutable_set(*items)
  MutableSet.new(set(*items))
end

.repeat(item) ⇒ List

Create an infinite list repeating the same item indefinitely

Examples:

Hamster.repeat(:chunky).take(4)
=> Hamster::List[:chunky, :chunky, :chunky, :chunky]

Returns:


60
61
62
# File 'lib/hamster/list.rb', line 60

def repeat(item)
  LazyList.new { Cons.new(item, repeat(item)) }
end

.replicate(number, item) ⇒ List

Create a list that contains a given item a fixed number of times

Examples:

Hamster.replicate(3, :hamster)
#=> Hamster::List[:hamster, :hamster, :hamster]

Returns:


71
72
73
# File 'lib/hamster/list.rb', line 71

def replicate(number, item)
  repeat(item).take(number)
end

.set(*items) ⇒ Object


11
12
13
# File 'lib/hamster/set.rb', line 11

def self.set(*items)
  items.empty? ? EmptySet : Set.new(items)
end

.sorted_set(*items, &block) ⇒ SortedSet

Create a new SortedSet populated with the given items. If a block is provided, it will determine the sort order of the set. Such a block can accept either 1 parameter (and will be used to derived sort keys, like a Enumerable#sort_by block) or 2 parameters (and will act as a comparator, like a Enumerable#sort block).

Returns:


14
15
16
# File 'lib/hamster/sorted_set.rb', line 14

def self.sorted_set(*items, &block)
  (items.empty? && block.nil?) ? EmptySortedSet : SortedSet.new(items, &block)
end

.stream(&block) ⇒ List

Create a lazy, infinite list.

The given block is called as necessary to return successive elements of the list.

Examples:

Hamster.stream { :hello }.take(3)
# => Hamster::List[:hello, :hello, :hello]

Returns:


34
35
36
37
# File 'lib/hamster/list.rb', line 34

def stream(&block)
  return EmptyList unless block_given?
  LazyList.new { Cons.new(yield, stream(&block)) }
end

.to_ruby(obj) ⇒ Hash, ...

Create a Ruby object from Hamster data. This method recursively "walks" the Hamster object, converting Hamster::Hash to Ruby Hash, Hamster::Vector to Ruby Array and Hamster::Set to Ruby `Set. Other Ruby objects are left as-is.

Examples:

h = Hamster.to_ruby(Hamster.from({ "a" => [1, 2], "b" => "c" }))
# => { "a" => [1, 2], "b" => "c" }

Returns:


55
56
57
58
59
60
61
62
63
64
65
66
67
68
# File 'lib/hamster/nested.rb', line 55

def to_ruby(obj)
  case obj
  when Hamster::Hash, ::Hash
    obj.each_with_object({}) { |keyval, hash| hash[to_ruby(keyval[0])] = to_ruby(keyval[1]) }
  when Hamster::Vector, ::Array
    obj.each_with_object([]) { |element, arr| arr << to_ruby(element) }
  when Hamster::Set, ::Set
    obj.each_with_object(::Set.new) { |element, set| set << to_ruby(element) }
  when Hamster::SortedSet, ::SortedSet
    obj.each_with_object(::SortedSet.new) { |element, set| set << to_ruby(element) }
  else
    obj
  end
end

.vector(*items) ⇒ Object

Create a new Vector populated with the given items. [Vector]


9
10
11
# File 'lib/hamster/vector.rb', line 9

def self.vector(*items)
  items.empty? ? EmptyVector : Vector.new(items.freeze)
end