Module: Immutable

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

Defined Under Namespace

Modules: Enumerable, List Classes: Deque, Hash, Set, SortedSet, Vector

Constant Summary collapse

VERSION =

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

'0.1.0'

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