Module: Immutable::Consable

Includes:
Headable
Included in:
Deque, List, OutputRestrictedDeque, Stream
Defined in:
lib/immutable/consable.rb

Defined Under Namespace

Modules: ClassMethods

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Headable

#==, #[], #each, #each_index, #empty?, #eql?, #fetch, #find, #first, #foldl, #foldl1, #foldr, #foldr1, #hash, #head, #index, #inspect, #null?, #rindex, #shift, #tail, #to_list

Methods included from Foldable

#foldl, #length, #product, #sum

Class Method Details

.included(c) ⇒ Object



68
69
70
# File 'lib/immutable/consable.rb', line 68

def self.included(c)
  c.extend(ClassMethods)
end

Instance Method Details

#+(xs) ⇒ Consable

Appends two Consable objects self and xs.

Parameters:

  • xs (Consable)

    the Consable object to append.

Returns:



101
102
103
# File 'lib/immutable/consable.rb', line 101

def +(xs)
  foldr(xs) { |y, ys| Cons(y, ys) }
end

#cons(x) ⇒ Consable

Adds a new element at the head of self. A class including Immutable::Consable must implement this method.

Parameters:

  • x (Object)

    the element to add.

Returns:

Raises:

  • (NotImplementedError)


77
78
79
# File 'lib/immutable/consable.rb', line 77

def cons(x)
  raise NotImplementedError
end

#drop(n) ⇒ Consable

Returns the suffix of self after the first n elements, or an empty Consable object if n > self.length.

Parameters:

  • n (Integer)

    the number of elements to drop.

Returns:

  • (Consable)

    the suffix of self after the first n elements.



221
222
223
224
225
226
227
228
229
230
231
# File 'lib/immutable/consable.rb', line 221

def drop(n)
  if empty?
    empty
  else
    if n > 0
      tail.drop(n - 1)
    else
      self
    end
  end
end

#drop_while(&block) ⇒ Consable

Returns the suffix remaining after self.take_while(&block).

Returns:

  • (Consable)

    the suffix of the elements of self.



253
254
255
256
257
258
259
260
261
262
263
# File 'lib/immutable/consable.rb', line 253

def drop_while(&block)
  if empty?
    empty
  else
    if yield(head)
      tail.drop_while(&block)
    else
      self
    end
  end
end

#filterConsable

Returns the elements in self for which the given block evaluates to true.

Returns:

  • (Consable)

    the elements that satisfies the condition.



269
270
271
272
273
274
275
276
277
# File 'lib/immutable/consable.rb', line 269

def filter
  foldr(empty) { |x, xs|
    if yield(x)
      Cons(x, xs)
    else
      xs
    end
  }
end

#flat_mapConsable Also known as: concat_map, bind

Returns the Consable object obtained by concatenating the results of the given block for each element in self.

Returns:

  • (Consable)

    the obtained Consable object.



192
193
194
# File 'lib/immutable/consable.rb', line 192

def flat_map
  foldr(empty) { |x, xs| safe_append(yield(x), xs) }
end

#flattenConsable Also known as: concat

Concatenates a Consable object of Consable objects.

Returns:

  • (Consable)

    the concatenated Consable object.



182
183
184
# File 'lib/immutable/consable.rb', line 182

def flatten
  foldr(empty) { |x, xs| safe_append(x, xs) }
end

#intercalate(xs) ⇒ Consable

Returns a new Consable object obtained by inserting xs in between the Consable objects in self and concatenates the result. xss.intercalate(xs) is equivalent to xss.intersperse(xs).flatten.

Parameters:

  • xs (Consable)

    the Consable object to insert between Consable objects.

Returns:

  • (Consable)

    the new Consable object.



148
149
150
# File 'lib/immutable/consable.rb', line 148

def intercalate(xs)
  intersperse(xs).flatten
end

#intersperse(sep) ⇒ Consable

Returns a new Consable object obtained by inserting sep in between the elements of self.

Parameters:

  • sep (Object)

    the object to insert between elements.

Returns:

  • (Consable)

    the new Consable object.



133
134
135
136
137
138
139
# File 'lib/immutable/consable.rb', line 133

def intersperse(sep)
  if empty?
    empty
  else
    Cons(head, tail.prepend_to_all(sep))
  end
end

#map(&block) ⇒ Consable

Returns the Consable object obtained by applying the given block to each element in self.

Returns:

  • (Consable)

    the obtained Consable object.



109
110
111
# File 'lib/immutable/consable.rb', line 109

def map(&block)
  rev_map(&block).reverse
end

#prepend(x) ⇒ Consable

Same as #cons. This method just calls #cons.

Parameters:

  • x (Object)

    the element to add.

Returns:



93
94
95
# File 'lib/immutable/consable.rb', line 93

def prepend(x)
  cons(x)
end

#rev_mapConsable

Returns the Consable object obtained by applying the given block to each element in self in reverse order.

Returns:

  • (Consable)

    the obtained Consable object.



117
118
119
# File 'lib/immutable/consable.rb', line 117

def rev_map
  foldl(empty) { |xs, x| Cons(yield(x), xs) }
end

#reverseConsable

Returns the elements of self in reverse order.

Returns:

  • (Consable)

    the reversed Consable object.



124
125
126
# File 'lib/immutable/consable.rb', line 124

def reverse
  foldl(empty) { |x, y| Cons(y, x) }
end

#subsequencesConsable<Consable>

Returns the Consable object of all subsequences of self.

Returns:



175
176
177
# File 'lib/immutable/consable.rb', line 175

def subsequences
  Cons(empty, nonempty_subsequences)
end

#take(n) ⇒ Consable

Returns the first n elements of self, or all the elements of self if n > self.length.

Parameters:

  • n (Integer)

    the number of elements to take.

Returns:

  • (Consable)

    the first n elements of self.



204
205
206
207
208
209
210
211
212
213
214
# File 'lib/immutable/consable.rb', line 204

def take(n)
  if empty?
    empty
  else
    if n <= 0
      empty
    else
      Cons(head, tail.take(n - 1))
    end
  end
end

#take_while(&block) ⇒ Consable

Returns the longest prefix of the elements of self for which block evaluates to true.

Returns:

  • (Consable)

    the prefix of the elements of self.



237
238
239
240
241
242
243
244
245
246
247
# File 'lib/immutable/consable.rb', line 237

def take_while(&block)
  if empty?
    empty
  else
    if yield(head)
      Cons(head, tail.take_while(&block))
    else
      empty
    end
  end
end

#transposeConsable

Transposes the rows and columns of self. For example:

p List[List[1, 2, 3], List[4, 5, 6]].transpose
#=> List[List[1, 4], List[2, 5], List[3, 6]]

Returns:

  • (Consable)

    the transposed Consable object.



158
159
160
161
162
163
164
165
166
167
168
169
170
# File 'lib/immutable/consable.rb', line 158

def transpose
  if empty?
    empty
  else
    if head.empty?
      tail.transpose
    else
      t = tail.filter { |x| !x.empty? }
      Cons(Cons(head.head, t.map(&:head)),
           Cons(head.tail, t.map(&:tail)).transpose)
    end
  end
end

#unshift(x) ⇒ Consable

Same as #cons. This method just calls #cons.

Parameters:

  • x (Object)

    the element to add.

Returns:



85
86
87
# File 'lib/immutable/consable.rb', line 85

def unshift(x)
  cons(x)
end

#zip(*xss) ⇒ Consable

Takes zero or more lists and returns a new Consable object in which each element is an array of the corresponding elements of self and the input Consable objects.

Parameters:

  • xss (Array<Consable>)

    the input Consable objects.

Returns:

  • (Consable)

    the new Consable object.



285
286
287
288
289
290
291
292
293
# File 'lib/immutable/consable.rb', line 285

def zip(*xss)
  if empty?
    empty
  else
    heads = xss.map { |xs| xs.empty? ? nil : xs.head }
    tails = xss.map { |xs| xs.empty? ? empty : xs.tail }
    Cons([head, *heads], tail.zip(*tails))
  end
end

#zip_with(*xss, &block) ⇒ Consable

Takes zero or more Consable objects and returns the Consable object obtained by applying the given block to an array of the corresponding elements of self and the input Consable objects. xs.zip_with(*yss, &block) is equivalent to xs.zip(*yss).map(&block).

Parameters:

  • xss (Array<Consable>)

    the input Consable objects.

Returns:

  • (Consable)

    the new Consable object.



303
304
305
306
307
308
309
310
311
# File 'lib/immutable/consable.rb', line 303

def zip_with(*xss, &block)
  if empty?
    empty
  else
    heads = xss.map { |xs| xs.null? ? nil : xs.head }
    tails = xss.map { |xs| xs.null? ? empty : xs.tail }
    Cons(yield(head, *heads), tail.zip_with(*tails, &block))
  end
end