module Hamster

Constants

EmptyDeque

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

@private

EmptyHash

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

@private

EmptySet

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

@private

EmptySortedSet

The canonical empty `SortedSet`. Returned by `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`.

@private

EmptyTrie

@private

EmptyVector

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

@private

VERSION

Current released gem version. Note that master will often have the same value as a release gem but with different code.

Public Class Methods

enumerate(enum) click to toggle source

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.

@example

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

@param enum [Enumerator] The object to iterate over @return [List]

# File lib/hamster/list.rb, line 92
def enumerate(enum)
  LazyList.new do
    begin
      Cons.new(enum.next, enumerate(enum))
    rescue StopIteration
      EmptyList
    end
  end
end
from(obj) click to toggle source

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}, Ruby `Set` to {Hamster::Set}, and Ruby `SortedSet` to {Hamster::SortedSet}. Other objects are left as-is.

@example

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

@return [Hash, Vector, Set, SortedSet, Object]

# File lib/hamster/nested.rb, line 24
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 ::Struct
    from(obj.to_h)
  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
interval(from, to) click to toggle source

Construct a list of consecutive integers.

@example

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

@param from [Integer] Start value, inclusive @param to [Integer] End value, inclusive @return [List]

# File lib/hamster/list.rb, line 36
def interval(from, to)
  return EmptyList if from > to
  interval_exclusive(from, to.next)
end
iterate(item) { |item| ... } click to toggle source

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

@example

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

@param [Object] item Starting value @yieldparam [Object] previous The previous value @yieldreturn [Object] The next value @return [List]

# File lib/hamster/list.rb, line 74
def iterate(item, &block)
  LazyList.new { Cons.new(item, iterate(yield(item), &block)) }
end
repeat(item) click to toggle source

Create an infinite list repeating the same item indefinitely

@example

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

@return [List]

# File lib/hamster/list.rb, line 48
def repeat(item)
  LazyList.new { Cons.new(item, repeat(item)) }
end
replicate(number, item) click to toggle source

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

@example

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

@return [List]

# File lib/hamster/list.rb, line 59
def replicate(number, item)
  repeat(item).take(number)
end
stream() { || ... } click to toggle source

Create a lazy, infinite list.

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

@example

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

@return [List]

# File lib/hamster/list.rb, line 22
def stream(&block)
  return EmptyList unless block_given?
  LazyList.new { Cons.new(yield, stream(&block)) }
end
to_ruby(obj) click to toggle source

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

@example

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

@return [::Hash, ::Array, ::Set, ::SortedSet, Object]

# File lib/hamster/nested.rb, line 61
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) }
  when Hamster::Deque
    obj.to_a.tap { |arr| arr.map! { |element| to_ruby(element) }}
  else
    obj
  end
end

Private Class Methods

interval_exclusive(from, to) click to toggle source
# File lib/hamster/list.rb, line 104
def interval_exclusive(from, to)
  return EmptyList if from == to
  LazyList.new { Cons.new(from, interval_exclusive(from.next, to)) }
end