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