Module: Immutable

Defined in:
lib/immutable/list.rb,
lib/immutable/trie.rb,
lib/immutable/_core.rb,
lib/immutable/deque.rb,
lib/immutable/nested.rb,
lib/immutable/version.rb,
lib/immutable/undefined.rb,
lib/immutable/enumerable.rb,
lib/immutable/sorted_set.rb

Defined Under Namespace

Modules: Enumerable, List, Undefined Classes: Cons, Deque, Hash, LazyList, Partitioned, Partitioner, Realizable, Set, SortedSet, Splitter, Trie, Vector

Constant Summary collapse

EmptyTrie =
Trie.new(0).freeze
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.

Immutable::Hash.empty
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.

Immutable::Vector.empty
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.

Immutable::Set.empty
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.

Immutable::Deque.empty
VERSION =

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

'0.2.0'
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.

Immutable::SortedSet.empty

Class Method Summary collapse

Class Method Details

.enumerate(enum) ⇒ List

Turn an Enumerator into a Immutable::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
Immutable.enumerate(to_enum(:rg)).take(10)

Parameters:

  • enum (Enumerator)

    The object to iterate over

Returns:



92
93
94
95
96
97
98
99
100
# File 'lib/immutable/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) ⇒ Hash, ...

Create a nested Immutable data structure from a nested Ruby object obj. This method recursively “walks” the Ruby object, converting Ruby Hash to Hash, Ruby Array to Vector, Ruby Set to Set, and Ruby SortedSet to SortedSet. Other objects are left as-is.

Examples:

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

Returns:



24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# File 'lib/immutable/nested.rb', line 24

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

.interval(from, to) ⇒ List

Construct a list of consecutive integers.

Examples:

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

Parameters:

  • from (Integer)

    Start value, inclusive

  • to (Integer)

    End value, inclusive

Returns:



36
37
38
39
# File 'lib/immutable/list.rb', line 36

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

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

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

Examples:

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

Parameters:

  • item (Object)

    Starting value

Yield Parameters:

  • previous (Object)

    The previous value

Yield Returns:

  • (Object)

    The next value

Returns:



74
75
76
# File 'lib/immutable/list.rb', line 74

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

.repeat(item) ⇒ List

Create an infinite list repeating the same item indefinitely

Examples:

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

Returns:



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

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:

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

Returns:



59
60
61
# File 'lib/immutable/list.rb', line 59

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

.stream(&block) ⇒ List

Create a lazy, infinite list.

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

Examples:

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

Returns:



22
23
24
25
# File 'lib/immutable/list.rb', line 22

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 Immutable data. This method recursively “walks” the Immutable object, converting Hash to Ruby Hash, Vector and Deque to Ruby Array, Set to Ruby Set, and SortedSet to Ruby SortedSet. Other objects are left as-is.

Examples:

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

Returns:

  • (::Hash, ::Array, ::Set, ::SortedSet, Object)


61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
# File 'lib/immutable/nested.rb', line 61

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