Module: Erlang::List

Includes:
Enumerable
Defined in:
lib/erlang/list.rb

Overview

A List can be constructed with List[]. It consists of a head (the first element) and a tail (which itself is also a List, containing all the remaining elements).

This is a singly linked list. Prepending to the list with #add runs in constant time. Traversing the list from front to back is efficient, however, indexed access runs in linear time because the list needs to be traversed to find the element.

Licensing

Portions taken and modified from https://github.com/hamstergem/hamster

Copyright (c) 2009-2014 Simon Harris

Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Enumerable

#compact, #each_index, #grep, #grep_v, #join, #product, #reject, #sum

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(name, *args, &block) ⇒ Object (private)



1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
# File 'lib/erlang/list.rb', line 1691

def method_missing(name, *args, &block)
  if name.to_s.match(CADR)
    code = "def #{name}; self."
    code << Regexp.last_match[1].reverse.chars.map do |char|
      {'a' => 'head', 'd' => 'tail'}[char]
    end.join('.')
    code << '; end'
    List.class_eval(code)
    send(name, *args, &block)
  else
    super
  end
end

Class Method Details

.[](*items) ⇒ List

Create a new List populated with the given items.

Examples:

list = Erlang::List[:a, :b, :c]
# => Erlang::List[:a, :b, :c]

Returns:



53
54
55
# File 'lib/erlang/list.rb', line 53

def self.[](*items)
  return from_enum(items)
end

.compare(a, b) ⇒ Object

Raises:

  • (ArgumentError)


93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
# File 'lib/erlang/list.rb', line 93

def self.compare(a, b)
  return Erlang::String.compare(a, b) if a.kind_of?(Erlang::String) and b.kind_of?(Erlang::String)
  a = a.to_list if a.kind_of?(Erlang::String)
  b = b.to_list if b.kind_of?(Erlang::String)
  raise ArgumentError, "'a' must be of Erlang::List type" if not a.kind_of?(Erlang::List)
  raise ArgumentError, "'b' must be of Erlang::List type" if not b.kind_of?(Erlang::List)
  c = 0
  while c == 0 and a.kind_of?(Erlang::List) and b.kind_of?(Erlang::List) and not a.empty? and not b.empty?
    c = Erlang.compare(a.head, b.head)
    a = a.tail
    b = b.tail
  end
  if c == 0
    if not a.kind_of?(Erlang::List) or not b.kind_of?(Erlang::List)
      c = Erlang.compare(a, b)
    elsif a.empty? and not b.empty?
      c = -1
    elsif not a.empty? and b.empty?
      c = 1
    end
  end
  return c
end

.emptyErlang::List

Return an empty Erlang::List.

Returns:



60
61
62
# File 'lib/erlang/list.rb', line 60

def self.empty
  return Erlang::Nil
end

Instance Method Details

#<<(item) ⇒ List

Create a new List with item added at the end. This is much less efficient than adding items at the front.

Examples:

Erlang::List[:a, :b] << :c
# => Erlang::List[:a, :b, :c]

Parameters:

  • item (Object)

    The item to add

Returns:

Raises:



140
141
142
143
# File 'lib/erlang/list.rb', line 140

def <<(item)
  raise Erlang::ImproperListError if improper?
  return append(Erlang::List[item])
end

#add(item) ⇒ List Also known as: cons

Create a new List with item added at the front. This is a constant time operation.

Examples:

Erlang::List[:b, :c].add(:a)
# => Erlang::List[:a, :b, :c]

Parameters:

  • item (Object)

    The item to add

Returns:



126
127
128
# File 'lib/erlang/list.rb', line 126

def add(item)
  return Erlang::Cons.new(item, self)
end

#append(other) ⇒ List Also known as: concat, +

Return a List with all items from this List, followed by all items from other.

Examples:

Erlang::List[1, 2, 3].append(Erlang::List[4, 5])
# => Erlang::List[1, 2, 3, 4, 5]

Parameters:

  • other (List)

    The list to add onto the end of this one

Returns:



399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
# File 'lib/erlang/list.rb', line 399

def append(other)
  # raise Erlang::ImproperListError if improper?
  other = Erlang.from(other)
  return self if not improper? and Erlang.is_list(other) and other.empty?
  return other if Erlang.is_list(other) and empty?
  is_improper = Erlang.is_list(other) ? other.improper? : true
  out = tail = Erlang::Cons.allocate
  list = self
  until list.empty?
    new_node = Erlang::Cons.allocate
    new_node.instance_variable_set(:@head, list.head)
    new_node.instance_variable_set(:@improper, is_improper)
    tail.instance_variable_set(:@tail, new_node)
    tail.instance_variable_set(:@improper, is_improper)
    tail.immutable!
    tail = new_node
    if not Erlang.is_list(list.tail)
      new_node = Erlang::Cons.allocate
      new_node.instance_variable_set(:@head, list.tail)
      new_node.instance_variable_set(:@improper, is_improper)
      tail.instance_variable_set(:@tail, new_node)
      tail.instance_variable_set(:@improper, is_improper)
      tail.immutable!
      tail = new_node
      list = Erlang::Nil
    else
      list = list.tail
    end
  end
  if not tail.immutable?
    tail.instance_variable_set(:@tail, other)
    tail.immutable!
  end
  return out.tail
end

#at(index) ⇒ Object

Retrieve the item at index. Negative indices count back from the end of the list (-1 is the last item). If index is invalid (either too high or too low), return nil.

Parameters:

  • index (Integer)

    The index to retrieve

Returns:

  • (Object)

Raises:



975
976
977
978
979
980
981
982
983
984
985
# File 'lib/erlang/list.rb', line 975

def at(index)
  raise Erlang::ImproperListError if improper?
  index += size if index < 0
  return nil if index < 0
  node = self
  while index > 0
    node = node.tail
    index -= 1
  end
  return node.head
end

#break {|item| ... } ⇒ Array

Return two Lists, one up to (but not including) the first item for which the block returns true, and another of all the remaining items.

Examples:

Erlang::List[1, 3, 4, 2, 5].break { |x| x > 3 }
# => [Erlang::List[1, 3], Erlang::List[4, 2, 5]]

Yields:

  • (item)

Returns:

  • (Array)

Raises:



578
579
580
581
582
# File 'lib/erlang/list.rb', line 578

def break(&block)
  raise Erlang::ImproperListError if improper?
  return span unless block_given?
  return span { |item| !yield(item) }
end

#chunk(number) ⇒ List

Split the items in this list in groups of number. Return a list of lists.

Examples:

("a".."o").to_list.chunk(5)
# => Erlang::List[
#      Erlang::List["a", "b", "c", "d", "e"],
#      Erlang::List["f", "g", "h", "i", "j"],
#      Erlang::List["k", "l", "m", "n", "o"]]

Returns:

Raises:



880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
# File 'lib/erlang/list.rb', line 880

def chunk(number)
  raise Erlang::ImproperListError if improper?
  return self if empty?
  out = tail = Erlang::Cons.allocate
  list = self
  until list.empty?
    first, list = list.split_at(number)
    new_node = Erlang::Cons.allocate
    new_node.instance_variable_set(:@head, first)
    new_node.instance_variable_set(:@improper, false)
    tail.instance_variable_set(:@tail, new_node)
    tail.instance_variable_set(:@improper, false)
    tail.immutable!
    tail = new_node
  end
  if not tail.immutable?
    tail.instance_variable_set(:@tail, Erlang::Nil)
    tail.immutable!
  end
  return out.tail
end

#clearList

Return an empty List. If used on a subclass, returns an empty instance of that class.

Returns:



588
589
590
# File 'lib/erlang/list.rb', line 588

def clear
  return Erlang::Nil
end

#combination(n) ⇒ List

Return a List of all combinations of length n of items from this List.

Examples:

Erlang::List[1,2,3].combination(2)
# => Erlang::List[
#      Erlang::List[1, 2],
#      Erlang::List[1, 3],
#      Erlang::List[2, 3]]

Returns:

Raises:



863
864
865
866
867
868
# File 'lib/erlang/list.rb', line 863

def combination(n)
  raise Erlang::ImproperListError if improper?
  return Erlang::Cons.new(Erlang::Nil) if n == 0
  return self if empty?
  return tail.combination(n - 1).map { |list| list.cons(head) }.append(tail.combination(n))
end

#delete(obj) ⇒ List

Return a List with all elements equal to obj removed. #== is used for testing equality.

Examples:

Erlang::List[:a, :b, :a, :a, :c].delete(:a) # => Erlang::List[:b, :c]

Parameters:

  • obj (Object)

    The object to remove.

Returns:

Raises:



1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
# File 'lib/erlang/list.rb', line 1213

def delete(obj)
  raise Erlang::ImproperListError if improper?
  obj = Erlang.from(obj)
  list = self
  list = list.tail while list.head == obj && !list.empty?
  return Erlang::Nil if list.empty?
  out = tail = Erlang::Cons.allocate
  until list.empty?
    if list.head == obj
      list = list.tail
    else
      new_node = Erlang::Cons.allocate
      new_node.instance_variable_set(:@head, list.head)
      new_node.instance_variable_set(:@improper, false)
      tail.instance_variable_set(:@tail, new_node)
      tail.instance_variable_set(:@improper, false)
      tail.immutable!
      tail = new_node
      list = list.tail
    end
  end
  if not tail.immutable?
    tail.instance_variable_set(:@tail, Erlang::Nil)
    tail.immutable!
  end
  return out.tail
end

#delete_at(index) ⇒ List

Return a List containing the same items, minus the one at index. If index is negative, it counts back from the end of the list.

Examples:

Erlang::List[1, 2, 3].delete_at(1)  # => Erlang::List[1, 3]
Erlang::List[1, 2, 3].delete_at(-1) # => Erlang::List[1, 2]

Parameters:

  • index (Integer)

    The index of the item to remove

Returns:

Raises:



1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
# File 'lib/erlang/list.rb', line 1250

def delete_at(index)
  raise Erlang::ImproperListError if improper?
  if index == 0
    tail
  elsif index < 0
    index += size if index < 0
    return self if index < 0
    delete_at(index)
  else
    out = tail = Erlang::Cons.allocate
    list = self
    while index > 0
      new_node = Erlang::Cons.allocate
      new_node.instance_variable_set(:@head, list.head)
      new_node.instance_variable_set(:@improper, false)
      tail.instance_variable_set(:@tail, new_node)
      tail.instance_variable_set(:@improper, false)
      tail.immutable!
      tail = new_node
      list = list.tail
      index -= 1
    end
    if not tail.immutable?
      tail.instance_variable_set(:@tail, list.tail)
      tail.immutable!
    end
    return out.tail
  end
end

#drop(number) ⇒ List

Return a List containing all items after the first number items from this List.

Examples:

Erlang::List[1, 3, 5, 7, 6, 4, 2].drop(3)
# => Erlang::List[7, 6, 4, 2]

Parameters:

  • number (Integer)

    The number of items to skip over

Returns:

Raises:



380
381
382
383
384
385
386
387
388
# File 'lib/erlang/list.rb', line 380

def drop(number)
  raise Erlang::ImproperListError if improper?
  list = self
  while !list.empty? && number > 0
    number -= 1
    list = list.tail
  end
  return list
end

#drop_while {|item| ... } ⇒ List, Enumerator

Return a List which contains all elements starting from the first element for which the block returns nil or false.

Examples:

Erlang::List[1, 3, 5, 7, 6, 4, 2].drop_while { |e| e < 5 }
# => Erlang::List[5, 7, 6, 4, 2]

Yields:

  • (item)

Returns:

  • (List, Enumerator)

Raises:



317
318
319
320
321
322
323
# File 'lib/erlang/list.rb', line 317

def drop_while(&block)
  raise Erlang::ImproperListError if improper?
  return enum_for(:drop_while) unless block_given?
  list = self
  list = list.tail while !list.empty? && yield(list.head)
  return list
end

#dupList Also known as: clone

Return self. Since this is an immutable object duplicates are equivalent.

Returns:



1550
1551
1552
# File 'lib/erlang/list.rb', line 1550

def dup
  return self
end

#each {|item| ... } ⇒ self

Call the given block once for each item in the list, passing each item from first to last successively to the block. If no block is given, returns an Enumerator.

Yields:

  • (item)

Returns:

  • (self)

Raises:



151
152
153
154
155
156
157
158
159
160
# File 'lib/erlang/list.rb', line 151

def each
  raise Erlang::ImproperListError if improper?
  return to_enum unless block_given?
  list = self
  until list.empty?
    yield(list.head)
    list = list.tail
  end
  return self
end

#each_chunk(number) {|list| ... } ⇒ self, Enumerator Also known as: each_slice

Split the items in this list in groups of number, and yield each group to the block (as a List). If no block is given, returns an Enumerator.

Yields:

  • (list)

    Once for each chunk.

Returns:

  • (self, Enumerator)

Raises:



908
909
910
911
912
913
# File 'lib/erlang/list.rb', line 908

def each_chunk(number, &block)
  raise Erlang::ImproperListError if improper?
  return enum_for(:each_chunk, number) unless block_given?
  chunk(number).each(&block)
  return self
end

#eql?(other) ⇒ Boolean Also known as: ==

Return true if other has the same type and contents as this Hash.

Parameters:

  • other (Object)

    The collection to compare with

Returns:

  • (Boolean)


1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
# File 'lib/erlang/list.rb', line 1500

def eql?(other)
  return true if other.equal?(self)
  if other.kind_of?(Erlang::List)
    return false if other.kind_of?(Erlang::List) and improper? != other.improper?
    return false if not other.kind_of?(Erlang::List) and improper?
    other = Erlang::List.from_enum(other) if other.is_a?(::Array)
    return false if not other.kind_of?(Erlang::List)
    list = self
    while Erlang.is_list(list) and Erlang.is_list(other) and !list.empty? and !other.empty?
      return true if other.equal?(list)
      return other.empty? if list.empty?
      return false if other.empty?
      return false if not other.head.eql?(list.head)
      list = list.tail
      other = other.tail
    end
    return true if other.equal?(list)
    return list.eql?(other) if not Erlang.is_list(list) and not Erlang.is_list(other)
    return false if not Erlang.is_list(list) or not Erlang.is_list(other)
    return other.empty? if list.empty?
    return false
  else
    return !!(Erlang.compare(other, self) == 0)
  end
end

#erlang_inspect(raw = false) ⇒ String

Allows this Map to be printed using Erlang.inspect().

Returns:



1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
# File 'lib/erlang/list.rb', line 1626

def erlang_inspect(raw = false)
  if improper?
    result = '['
    to_proper_list.each_with_index { |obj, i| result << ',' if i > 0; result << Erlang.inspect(obj, raw: raw) }
    result << '|'
    result << Erlang.inspect(last(true), raw: raw)
    result << ']'
    return result
  else
    result = '['
    each_with_index { |obj, i| result << ',' if i > 0; result << Erlang.inspect(obj, raw: raw) }
    result << ']'
    return result
  end
end

#fill(object) ⇒ List #fill(object, index) ⇒ List #fill(object, index, length) ⇒ List

Replace a range of indexes with the given object.

Overloads:

  • #fill(object) ⇒ List

    Return a new List of the same size, with every index set to object.

    Examples:

    Erlang::List["A", "B", "C", "D", "E", "F"].fill("Z")
    # => Erlang::List["Z", "Z", "Z", "Z", "Z", "Z"]

    Parameters:

    • object (Object)

      Fill value.

  • #fill(object, index) ⇒ List

    Return a new List with all indexes from index to the end of the vector set to obj.

    Examples:

    Erlang::List["A", "B", "C", "D", "E", "F"].fill("Z", 3)
    # => Erlang::List["A", "B", "C", "Z", "Z", "Z"]

    Parameters:

    • object (Object)

      Fill value.

    • index (Integer)

      Starting index. May be negative.

  • #fill(object, index, length) ⇒ List

    Return a new List with length indexes, beginning from index, set to obj. Expands the List if length would extend beyond the current length.

    Examples:

    Erlang::List["A", "B", "C", "D", "E", "F"].fill("Z", 3, 2)
    # => Erlang::List["A", "B", "C", "Z", "Z", "F"]
    Erlang::List["A", "B"].fill("Z", 1, 5)
    # => Erlang::List["A", "Z", "Z", "Z", "Z", "Z"]

    Parameters:

    • object (Object)

      Fill value.

    • index (Integer)

      Starting index. May be negative.

    • length (Integer)

Returns:

Raises:

  • (IndexError)

    if index is out of negative range.



1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
# File 'lib/erlang/list.rb', line 1316

def fill(obj, index = 0, length = nil)
  raise Erlang::ImproperListError if improper?
  obj = Erlang.from(obj)
  if index == 0
    length ||= size
    if length > 0
      out = tail = Erlang::Cons.allocate
      list = self
      while length > 0
        new_node = Erlang::Cons.allocate
        new_node.instance_variable_set(:@head, obj)
        new_node.instance_variable_set(:@improper, false)
        tail.instance_variable_set(:@tail, new_node)
        tail.instance_variable_set(:@improper, false)
        tail.immutable!
        tail = new_node
        list = list.tail
        length -= 1
      end
      if not tail.immutable?
        tail.instance_variable_set(:@tail, list)
        tail.immutable!
      end
      return out.tail
    else
      self
    end
  elsif index > 0
    length ||= size - index
    length = 0 if length < 0
    out = tail = Erlang::Cons.allocate
    list = self
    while index > 0
      new_node = Erlang::Cons.allocate
      new_node.instance_variable_set(:@head, list.head)
      new_node.instance_variable_set(:@improper, false)
      tail.instance_variable_set(:@tail, new_node)
      tail.instance_variable_set(:@improper, false)
      tail.immutable!
      tail = new_node
      list = list.tail
      index -= 1
    end
    while length > 0
      new_node = Erlang::Cons.allocate
      new_node.instance_variable_set(:@head, obj)
      new_node.instance_variable_set(:@improper, false)
      tail.instance_variable_set(:@tail, new_node)
      tail.instance_variable_set(:@improper, false)
      tail.immutable!
      tail = new_node
      list = list.tail
      length -= 1
    end
    if not tail.immutable?
      tail.instance_variable_set(:@tail, list)
      tail.immutable!
    end
    return out.tail
  else
    raise IndexError if index < -size
    return fill(obj, index + size, length)
  end
end

#flat_map(&block) ⇒ List

Return a List which is realized by transforming each item into a List, and flattening the resulting lists.

Examples:

Erlang::List[1, 2, 3].flat_map { |x| Erlang::List[x, 100] }
# => Erlang::List[1, 100, 2, 100, 3, 100]

Returns:

Raises:



203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
# File 'lib/erlang/list.rb', line 203

def flat_map(&block)
  raise Erlang::ImproperListError if improper?
  return enum_for(:flat_map) unless block_given?
  return self if empty?
  out = tail = Erlang::Cons.allocate
  list = self
  until list.empty?
    head_list = Erlang::List.from_enum(yield(list.head))
    if head_list.empty?
      list = list.tail
    elsif list.tail.empty?
      tail.instance_variable_set(:@head, head_list.head)
      tail.instance_variable_set(:@tail, head_list.tail)
      tail.immutable!
      list = list.tail
    else
      new_node = Erlang::Cons.allocate
      new_node.instance_variable_set(:@improper, false)
      tail.instance_variable_set(:@head, head_list.head)
      tail.instance_variable_set(:@tail, head_list.tail + new_node)
      tail.immutable!
      list = list.tail
      tail = new_node
    end
  end
  if not tail.immutable?
    tail.instance_variable_set(:@tail, Erlang::Nil)
    tail.immutable!
  end
  if out === tail and not out.tail.kind_of?(Erlang::List)
    return out.tail
  else
    return out
  end
end

#flattenList

Return a new List with all nested lists recursively "flattened out", that is, their elements inserted into the new List in the place where the nested list originally was.

Examples:

Erlang::List[Erlang::List[1, 2], Erlang::List[3, 4]].flatten
# => Erlang::List[1, 2, 3, 4]

Returns:

Raises:



925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
# File 'lib/erlang/list.rb', line 925

def flatten
  raise Erlang::ImproperListError if improper?
  return self if empty?
  out = tail = Erlang::Cons.allocate
  list = self
  until list.empty?
    if list.head.is_a?(Erlang::Cons)
      list = list.head.append(list.tail)
    elsif Erlang::Nil.equal?(list.head)
      list = list.tail
    else
      new_node = Erlang::Cons.allocate
      new_node.instance_variable_set(:@head, list.head)
      new_node.instance_variable_set(:@improper, false)
      tail.instance_variable_set(:@tail, new_node)
      tail.immutable!
      list = list.tail
      tail = new_node
    end
  end
  if not tail.immutable?
    tail.instance_variable_set(:@tail, Erlang::Nil)
    tail.immutable!
  end
  return out.tail
end

#group_by {|item| ... } ⇒ Map Also known as: group

Passes each item to the block, and gathers them into a Map where the keys are return values from the block, and the values are Lists of items for which the block returned that value.

Examples:

Erlang::List["a", "b", "ab"].group_by { |e| e.size }
# Erlang::Map[
#   1 => Erlang::List["b", "a"],
#   2 => Erlang::List["ab"]
# ]

Yields:

  • (item)

Returns:



964
965
966
# File 'lib/erlang/list.rb', line 964

def group_by(&block)
  return group_by_with(Erlang::Nil, &block)
end

#hashInteger

See Object#hash

Returns:

  • (Integer)


1529
1530
1531
1532
1533
1534
1535
1536
1537
# File 'lib/erlang/list.rb', line 1529

def hash
  if improper?
    hash = to_proper_list.hash
    return (hash << 5) - hash + last(true).hash
  else
    hash = reduce(0) { |acc, item| (acc << 5) - acc + item.hash }
    return (hash << 5) - hash + Erlang::Nil.hash
  end
end

#indices(object) ⇒ List #indices {|item| ... } ⇒ List

Return a List of indices of matching objects.

Overloads:

  • #indices(object) ⇒ List

    Return a List of indices where object is found. Use #== for testing equality.

    Examples:

    Erlang::List[1, 2, 3, 4].indices(2)
    # => Erlang::List[1]
  • #indices {|item| ... } ⇒ List

    Pass each item successively to the block. Return a list of indices where the block returns true.

    Examples:

    Erlang::List[1, 2, 3, 4].indices { |e| e.even? }
    # => Erlang::List[1, 3]

    Yields:

    • (item)

Returns:

Raises:



1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
# File 'lib/erlang/list.rb', line 1083

def indices(object = Erlang::Undefined, i = 0, &block)
  raise Erlang::ImproperListError if improper?
  object = Erlang.from(object) if object != Erlang::Undefined
  return indices { |item| item == object } if not block_given?
  return Erlang::Nil if empty?
  out = tail = Erlang::Cons.allocate
  list = self
  until list.empty?
    if yield(list.head)
      new_node = Erlang::Cons.allocate
      new_node.instance_variable_set(:@head, i)
      new_node.instance_variable_set(:@improper, false)
      tail.instance_variable_set(:@tail, new_node)
      tail.instance_variable_set(:@improper, false)
      tail.immutable!
      tail = new_node
      list = list.tail
    else
      list = list.tail
    end
    i += 1
  end
  if not tail.immutable?
    tail.instance_variable_set(:@tail, Erlang::Nil)
    tail.immutable!
  end
  return out.tail
end

#initList

Return a List with all elements except the last one.

Examples:

Erlang::List["a", "b", "c"].init # => Erlang::List["a", "b"]

Returns:

Raises:



766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
# File 'lib/erlang/list.rb', line 766

def init
  raise Erlang::ImproperListError if improper?
  return Erlang::Nil if tail.empty?
  out = tail = Erlang::Cons.allocate
  list = self
  until list.tail.empty?
    new_node = Erlang::Cons.allocate
    new_node.instance_variable_set(:@head, list.head)
    new_node.instance_variable_set(:@improper, false)
    tail.instance_variable_set(:@tail, new_node)
    tail.instance_variable_set(:@improper, false)
    tail.immutable!
    tail = new_node
    list = list.tail
  end
  if not tail.immutable?
    tail.instance_variable_set(:@tail, Erlang::Nil)
    tail.immutable!
  end
  return out.tail
end

#initsList

Return a List of all prefixes of this list.

Examples:

Erlang::List[1,2,3].inits
# => Erlang::List[
#      Erlang::List[1],
#      Erlang::List[1, 2],
#      Erlang::List[1, 2, 3]]

Returns:

Raises:



840
841
842
843
844
845
846
847
848
849
850
851
# File 'lib/erlang/list.rb', line 840

def inits
  raise Erlang::ImproperListError if improper?
  return self if empty?
  prev = nil
  return map do |head|
    if prev.nil?
      Erlang::List.from_enum(prev = [head])
    else
      Erlang::List.from_enum(prev.push(head))
    end
  end
end

#insert(index, *items) ⇒ List

Return a new List with the given items inserted before the item at index.

Examples:

Erlang::List["A", "D", "E"].insert(1, "B", "C") # => Erlang::List["A", "B", "C", "D", "E"]

Parameters:

  • index (Integer)

    The index where the new items should go

  • items (Array)

    The items to add

Returns:

Raises:



1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
# File 'lib/erlang/list.rb', line 1176

def insert(index, *items)
  raise Erlang::ImproperListError if improper?
  if index == 0
    return Erlang::List.from_enum(items).append(self)
  elsif index > 0
    out = tail = Erlang::Cons.allocate
    list = self
    while index > 0
      new_node = Erlang::Cons.allocate
      new_node.instance_variable_set(:@head, list.head)
      new_node.instance_variable_set(:@improper, false)
      tail.instance_variable_set(:@tail, new_node)
      tail.instance_variable_set(:@improper, false)
      tail.immutable!
      tail = new_node
      list = list.tail
      index -= 1
    end
    if not tail.immutable?
      tail.instance_variable_set(:@tail, Erlang::List.from_enum(items).append(list))
      tail.immutable!
    end
    return out.tail
  else
    raise IndexError if index < -size
    return insert(index + size, *items)
  end
end

#inspect::String

Return the contents of this List as a programmer-readable String. If all the items in the list are serializable as Ruby literal strings, the returned string can be passed to eval to reconstitute an equivalent List.

Returns:

  • (::String)


1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
# File 'lib/erlang/list.rb', line 1647

def inspect
  if improper?
    result = 'Erlang::List['
    list = to_proper_list
    list.each_with_index { |obj, i| result << ', ' if i > 0; result << obj.inspect }
    result << ']'
    result << " + #{last(true).inspect}"
    return result
  else
    result = '['
    list = self
    list.each_with_index { |obj, i| result << ', ' if i > 0; result << obj.inspect }
    result << ']'
    return result
  end
end

#intersperse(sep) ⇒ List

Return a new List with sep inserted between each of the existing elements.

Examples:

Erlang::List["one", "two", "three"].intersperse(" ")
# => Erlang::List["one", " ", "two", " ", "three"]

Returns:

Raises:



645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
# File 'lib/erlang/list.rb', line 645

def intersperse(sep)
  raise Erlang::ImproperListError if improper?
  return self if tail.empty?
  sep = Erlang.from(sep)
  out = tail = Erlang::Cons.allocate
  list = self
  until list.empty?
    new_node = Erlang::Cons.allocate
    new_node.instance_variable_set(:@head, list.head)
    new_node.instance_variable_set(:@improper, false)
    if not list.tail.empty?
      sep_node = Erlang::Cons.allocate
      sep_node.instance_variable_set(:@head, sep)
      sep_node.instance_variable_set(:@improper, false)
      new_node.instance_variable_set(:@tail, sep_node)
      new_node.immutable!
    end
    tail.instance_variable_set(:@tail, new_node)
    tail.instance_variable_set(:@improper, false)
    tail.immutable!
    if list.tail.empty?
      tail = new_node
    else
      tail = new_node.tail
    end
    list = list.tail
  end
  if not tail.immutable?
    tail.instance_variable_set(:@tail, Erlang::Nil)
    tail.immutable!
  end
  return out.tail
end

#last(allow_improper = false) ⇒ Object

Return the last item in this list.

Returns:

  • (Object)


790
791
792
793
794
795
796
797
798
799
800
801
# File 'lib/erlang/list.rb', line 790

def last(allow_improper = false)
  if allow_improper and improper?
    list = self
    list = list.tail while list.tail.kind_of?(Erlang::List)
    return list.tail
  else
    raise Erlang::ImproperListError if improper?
    list = self
    list = list.tail until list.tail.empty?
    return list.head
  end
end

#map {|item| ... } ⇒ List, Enumerator Also known as: collect

Return a List in which each element is derived from the corresponding element in this List, transformed through the given block. If no block is given, returns an Enumerator.

Examples:

Erlang::List[3, 2, 1].map { |e| e * e } # => Erlang::List[9, 4, 1]

Yields:

  • (item)

Returns:

  • (List, Enumerator)

Raises:



171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
# File 'lib/erlang/list.rb', line 171

def map(&block)
  raise Erlang::ImproperListError if improper?
  return enum_for(:map) unless block_given?
  return self if empty?
  out = tail = Erlang::Cons.allocate
  list = self
  until list.empty?
    new_node = Erlang::Cons.allocate
    new_node.instance_variable_set(:@head, Erlang.from(yield(list.head)))
    new_node.instance_variable_set(:@improper, false)
    tail.instance_variable_set(:@tail, new_node)
    tail.instance_variable_set(:@improper, false)
    tail.immutable!
    tail = new_node
    list = list.tail
  end
  if not tail.immutable?
    tail.instance_variable_set(:@tail, Erlang::Nil)
    tail.immutable!
  end
  return out.tail
end

#merge {|a, b| ... } ⇒ List

Merge all the nested lists into a single list, using the given comparator block to determine the order which items should be shifted out of the nested lists and into the output list.

Examples:

list_1 = Erlang::List[1, -3, -5]
list_2 = Erlang::List[-2, 4, 6]
Erlang::List[list_1, list_2].merge { |a,b| a.abs <=> b.abs }
# => Erlang::List[1, -2, -3, 4, -5, 6]

Yields:

  • (a, b)

    Pairs of items from matching indices in each list.

Yield Returns:

  • (Integer)

    Negative if the first element should be selected first, positive if the latter element, or zero if either.

Returns:

Raises:



1127
1128
1129
1130
1131
1132
1133
1134
1135
# File 'lib/erlang/list.rb', line 1127

def merge(&comparator)
  raise Erlang::ImproperListError if improper?
  return merge_by unless block_given?
  sorted = reject(&:empty?).sort do |a, b|
    yield(a.head, b.head)
  end
  return Erlang::Nil if sorted.empty?
  return Erlang::Cons.new(sorted.head.head, sorted.tail.cons(sorted.head.tail).merge(&comparator))
end

#merge_by {|item| ... } ⇒ List

Merge all the nested lists into a single list, using sort keys generated by mapping the items in the nested lists through the given block to determine the order which items should be shifted out of the nested lists and into the output list. Whichever nested list's #head has the "lowest" sort key (according to their natural order) will be the first in the merged List.

Examples:

list_1 = Erlang::List[1, -3, -5]
list_2 = Erlang::List[-2, 4, 6]
Erlang::List[list_1, list_2].merge_by { |x| x.abs }
# => Erlang::List[1, -2, -3, 4, -5, 6]

Yields:

  • (item)

    Once for each item in either list.

Yield Returns:

  • (Object)

    A sort key for the element.

Returns:

Raises:



1152
1153
1154
1155
1156
1157
1158
1159
1160
# File 'lib/erlang/list.rb', line 1152

def merge_by(&transformer)
  raise Erlang::ImproperListError if improper?
  return merge_by { |item| item } unless block_given?
  sorted = reject(&:empty?).sort_by do |list|
    yield(list.head)
  end
  return Erlang::Nil if sorted.empty?
  return Erlang::Cons.new(sorted.head.head, sorted.tail.cons(sorted.head.tail).merge_by(&transformer))
end

#partition {|item| ... } ⇒ Tuple

Return two Lists, the first containing all the elements for which the block evaluates to true, the second containing the rest.

Examples:

Erlang::List[1, 2, 3, 4, 5, 6].partition { |x| x.even? }
# => Erlang::Tuple[Erlang::List[2, 4, 6], Erlang::List[1, 3, 5]]

Yields:

  • (item)

    Once for each item.

Returns:

Raises:



1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
# File 'lib/erlang/list.rb', line 1458

def partition(&block)
  raise Erlang::ImproperListError if improper?
  return enum_for(:partition) if not block_given?
  left = left_tail = Erlang::Cons.allocate
  right = right_tail = Erlang::Cons.allocate
  list = self
  while !list.empty?
    if yield(list.head)
      new_node = Erlang::Cons.allocate
      new_node.instance_variable_set(:@head, list.head)
      new_node.instance_variable_set(:@improper, false)
      left_tail.instance_variable_set(:@tail, new_node)
      left_tail.instance_variable_set(:@improper, false)
      left_tail.immutable!
      left_tail = new_node
      list = list.tail
    else
      new_node = Erlang::Cons.allocate
      new_node.instance_variable_set(:@head, list.head)
      new_node.instance_variable_set(:@improper, false)
      right_tail.instance_variable_set(:@tail, new_node)
      right_tail.instance_variable_set(:@improper, false)
      right_tail.immutable!
      right_tail = new_node
      list = list.tail
    end
  end
  if not left_tail.immutable?
    left_tail.instance_variable_set(:@tail, Erlang::Nil)
    left_tail.immutable!
  end
  if not right_tail.immutable?
    right_tail.instance_variable_set(:@tail, Erlang::Nil)
    right_tail.immutable!
  end
  return Erlang::Tuple[left.tail, right.tail]
end

#permutation(length = size) {|list| ... } ⇒ self, Enumerator

Yields all permutations of length n of the items in the list, and then returns self. If no length n is specified, permutations of the entire list will be yielded.

There is no guarantee about which order the permutations will be yielded in.

If no block is given, an Enumerator is returned instead.

Examples:

Erlang::List[1, 2, 3].permutation.to_a
# => [Erlang::List[1, 2, 3],
#     Erlang::List[2, 1, 3],
#     Erlang::List[2, 3, 1],
#     Erlang::List[1, 3, 2],
#     Erlang::List[3, 1, 2],
#     Erlang::List[3, 2, 1]]

Yields:

  • (list)

    Once for each permutation.

Returns:

  • (self, Enumerator)

Raises:



1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
# File 'lib/erlang/list.rb', line 1400

def permutation(length = size, &block)
  raise Erlang::ImproperListError if improper?
  return enum_for(:permutation, length) if not block_given?
  if length == 0
    yield Erlang::Nil
  elsif length == 1
    each { |obj| yield Erlang::Cons.new(obj, Erlang::Nil) }
  elsif not empty?
    if length < size
      tail.permutation(length, &block)
    end

    tail.permutation(length-1) do |p|
      0.upto(length-1) do |i|
        left,right = p.split_at(i)
        yield left.append(right.cons(head))
      end
    end
  end
  return self
end

#popList

Return a List containing all but the last item from this List.

Examples:

Erlang::List["A", "B", "C"].pop  # => Erlang::List["A", "B"]

Returns:

Raises:



363
364
365
366
367
368
369
# File 'lib/erlang/list.rb', line 363

def pop
  raise Erlang::ImproperListError if improper?
  return self if empty?
  new_size = size - 1
  return Erlang::List.new(head, tail.take(new_size - 1)) if new_size >= 1
  return Erlang::Nil
end

#reverseList

Return a List with the same items, but in reverse order.

Examples:

Erlang::List["A", "B", "C"].reverse # => Erlang::List["C", "B", "A"]

Returns:



443
444
445
# File 'lib/erlang/list.rb', line 443

def reverse
  return reduce(Erlang::Nil) { |list, item| list.cons(item) }
end

#rotate(count = 1) ⇒ List

Return a new List with the same elements, but rotated so that the one at index count is the first element of the new list. If count is positive, the elements will be shifted left, and those shifted past the lowest position will be moved to the end. If count is negative, the elements will be shifted right, and those shifted past the last position will be moved to the beginning.

Examples:

l = Erlang::List["A", "B", "C", "D", "E", "F"]
l.rotate(2)   # => Erlang::List["C", "D", "E", "F", "A", "B"]
l.rotate(-1)  # => Erlang::List["F", "A", "B", "C", "D", "E"]

Parameters:

  • count (Integer) (defaults to: 1)

    The number of positions to shift items by

Returns:

Raises:

  • (TypeError)

    if count is not an integer.



513
514
515
516
517
518
519
# File 'lib/erlang/list.rb', line 513

def rotate(count = 1)
  raise Erlang::ImproperListError if improper?
  raise TypeError, "expected Integer" if not count.is_a?(Integer)
  return self if empty? || (count % size) == 0
  count = (count >= 0) ? count % size : (size - (~count % size) - 1)
  return drop(count).append(take(count))
end

#sampleObject

Return a randomly chosen element from this list.

Returns:

  • (Object)


1164
1165
1166
# File 'lib/erlang/list.rb', line 1164

def sample
  return at(rand(size))
end

#select {|item| ... } ⇒ List Also known as: find_all, keep_if

Return a List which contains all the items for which the given block returns true.

Examples:

Erlang::List["Bird", "Cow", "Elephant"].select { |e| e.size >= 4 }
# => Erlang::List["Bird", "Elephant"]

Yields:

  • (item)

    Once for each item.

Returns:

Raises:



248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
# File 'lib/erlang/list.rb', line 248

def select(&block)
  raise Erlang::ImproperListError if improper?
  return enum_for(:select) unless block_given?
  out = tail = Erlang::Cons.allocate
  list = self
  while !list.empty?
    if yield(list.head)
      new_node = Erlang::Cons.allocate
      new_node.instance_variable_set(:@head, list.head)
      new_node.instance_variable_set(:@improper, false)
      tail.instance_variable_set(:@tail, new_node)
      tail.instance_variable_set(:@improper, false)
      tail.immutable!
      tail = new_node
      list = list.tail
    else
      list = list.tail
    end
  end
  if not tail.immutable?
    tail.instance_variable_set(:@tail, Erlang::Nil)
    tail.immutable!
  end
  return out.tail
end

#list.slice(index) ⇒ Object #list.slice(index, length) ⇒ List #list.slice(index..end) ⇒ Vector Also known as: []

Return specific objects from the List. All overloads return nil if the starting index is out of range.

Overloads:

  • #list.slice(index) ⇒ Object

    Returns a single object at the given index. If index is negative, count backwards from the end.

    Examples:

    l = Erlang::List["A", "B", "C", "D", "E", "F"]
    l[2]  # => "C"
    l[-1] # => "F"
    l[6]  # => nil

    Parameters:

    • index (Integer)

      The index to retrieve. May be negative.

    Returns:

    • (Object)
  • #list.slice(index, length) ⇒ List

    Return a sublist starting at index and continuing for length elements or until the end of the List, whichever occurs first.

    Examples:

    l = Erlang::List["A", "B", "C", "D", "E", "F"]
    l[2, 3]  # => Erlang::List["C", "D", "E"]
    l[-2, 3] # => Erlang::List["E", "F"]
    l[20, 1] # => nil

    Parameters:

    • start (Integer)

      The index to start retrieving items from. May be negative.

    • length (Integer)

      The number of items to retrieve.

    Returns:

  • #list.slice(index..end) ⇒ Vector

    Return a sublist starting at index and continuing to index end or the end of the List, whichever occurs first.

    Examples:

    l = Erlang::List["A", "B", "C", "D", "E", "F"]
    l[2..3]    # => Erlang::List["C", "D"]
    l[-2..100] # => Erlang::List["E", "F"]
    l[20..21]  # => nil

    Parameters:

    • range (Range)

      The range of indices to retrieve.

    Returns:

    • (Vector)

Raises:



1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
# File 'lib/erlang/list.rb', line 1027

def slice(arg, length = (missing_length = true))
  raise Erlang::ImproperListError if improper?
  if missing_length
    if arg.is_a?(Range)
      from, to = arg.begin, arg.end
      from += size if from < 0
      return nil if from < 0
      to   += size if to < 0
      to   += 1    if !arg.exclude_end?
      length = to - from
      length = 0 if length < 0
      list = self
      while from > 0
        return nil if list.empty?
        list = list.tail
        from -= 1
      end
      return list.take(length)
    else
      return at(arg)
    end
  else
    return nil if length < 0
    arg += size if arg < 0
    return nil if arg < 0
    list = self
    while arg > 0
      return nil if list.empty?
      list = list.tail
      arg -= 1
    end
    return list.take(length)
  end
end

#sortList #sort {|a, b| ... } ⇒ List

Return a new List with the same items, but sorted.

Overloads:

  • #sortList

    Compare elements with their natural sort key (#<=>).

    Examples:

    Erlang::List["Elephant", "Dog", "Lion"].sort
    # => Erlang::List["Dog", "Elephant", "Lion"]
  • #sort {|a, b| ... } ⇒ List

    Uses the block as a comparator to determine sorted order.

    Examples:

    Erlang::List["Elephant", "Dog", "Lion"].sort { |a,b| a.size <=> b.size }
    # => Erlang::List["Dog", "Lion", "Elephant"]

    Yields:

    • (a, b)

      Any number of times with different pairs of elements.

    Yield Returns:

    • (Integer)

      Negative if the first element should be sorted lower, positive if the latter element, or 0 if equal.

Returns:



613
614
615
616
617
# File 'lib/erlang/list.rb', line 613

def sort(&comparator)
  comparator = Erlang.method(:compare) unless block_given?
  array = super(&comparator)
  return List.from_enum(array)
end

#sort_by {|element| ... } ⇒ List

Return a new List with the same items, but sorted. The sort order is determined by mapping the items through the given block to obtain sort keys, and then sorting the keys according to their natural sort order (#<=>).

Examples:

Erlang::List["Elephant", "Dog", "Lion"].sort_by { |e| e.size }
# => Erlang::List["Dog", "Lion", "Elephant"]

Yields:

  • (element)

    Once for each element.

Yield Returns:

  • a sort key object for the yielded element.

Returns:



631
632
633
634
635
636
# File 'lib/erlang/list.rb', line 631

def sort_by(&transformer)
  return sort unless block_given?
  block = ->(x) { Erlang.from(transformer.call(x)) }
  array = super(&block)
  return List.from_enum(array)
end

#span {|item| ... } ⇒ Tuple

Return two Lists, one up to (but not including) the first item for which the block returns nil or false, and another of all the remaining items.

Examples:

Erlang::List[4, 3, 5, 2, 1].span { |x| x > 2 }
# => Erlang::Tuple[Erlang::List[4, 3, 5], Erlang::List[2, 1]]

Yields:

  • (item)

Returns:

Raises:



543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
# File 'lib/erlang/list.rb', line 543

def span(&block)
  raise Erlang::ImproperListError if improper?
  return [self, EmptyList].freeze unless block_given?
  left = left_tail = Erlang::Cons.allocate
  list = self
  while !list.empty?
    if yield(list.head)
      new_node = Erlang::Cons.allocate
      new_node.instance_variable_set(:@head, list.head)
      new_node.instance_variable_set(:@improper, false)
      left_tail.instance_variable_set(:@tail, new_node)
      left_tail.instance_variable_set(:@improper, false)
      left_tail.immutable!
      left_tail = new_node
      list = list.tail
    else
      break
    end
  end
  if not left_tail.immutable?
    left_tail.instance_variable_set(:@tail, Erlang::Nil)
    left_tail.immutable!
  end
  return Erlang::Tuple[left.tail, list]
end

#split_at(number) ⇒ Tuple

Return two Lists, one of the first number items, and another with the remaining.

Examples:

Erlang::List["a", "b", "c", "d"].split_at(2)
# => Erlang::Tuple[Erlang::List["a", "b"], Erlang::List["c", "d"]]

Parameters:

  • number (Integer)

    The index at which to split this list

Returns:



530
531
532
# File 'lib/erlang/list.rb', line 530

def split_at(number)
  return Erlang::Tuple[take(number), drop(number)]
end

#subsequences {|sublist| ... } ⇒ self

Yield every non-empty sublist to the given block. (The entire List also counts as one sublist.)

Examples:

Erlang::List[1, 2, 3].subsequences { |list| p list }
# prints:
# Erlang::List[1]
# Erlang::List[1, 2]
# Erlang::List[1, 2, 3]
# Erlang::List[2]
# Erlang::List[2, 3]
# Erlang::List[3]

Yields:

  • (sublist)

    One or more contiguous elements from this list

Returns:

  • (self)

Raises:



1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
# File 'lib/erlang/list.rb', line 1437

def subsequences(&block)
  raise Erlang::ImproperListError if improper?
  return enum_for(:subsequences) if not block_given?
  if not empty?
    1.upto(size) do |n|
      yield take(n)
    end
    tail.subsequences(&block)
  end
  return self
end

#tailsList

Return a List of all suffixes of this list.

Examples:

Erlang::List[1,2,3].tails
# => Erlang::List[
#      Erlang::List[1, 2, 3],
#      Erlang::List[2, 3],
#      Erlang::List[3]]

Returns:

Raises:



813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
# File 'lib/erlang/list.rb', line 813

def tails
  raise Erlang::ImproperListError if improper?
  return self if empty?
  out = tail = Erlang::Cons.allocate
  list = self
  until list.empty?
    new_node = Erlang::Cons.allocate
    new_node.instance_variable_set(:@head, list)
    new_node.instance_variable_set(:@improper, false)
    tail.instance_variable_set(:@tail, new_node)
    list = list.tail
    tail = new_node
  end
  tail.instance_variable_set(:@tail, Erlang::Nil)
  return out.tail
end

#take(number) ⇒ List

Return a List containing the first number items from this List.

Examples:

Erlang::List[1, 3, 5, 7, 6, 4, 2].take(3)
# => Erlang::List[1, 3, 5]

Parameters:

  • number (Integer)

    The number of items to retain

Returns:

Raises:



333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
# File 'lib/erlang/list.rb', line 333

def take(number)
  raise Erlang::ImproperListError if improper?
  return self if empty?
  return Erlang::Nil if number <= 0
  out = tail = Erlang::Cons.allocate
  list = self
  while !list.empty? && number > 0
    new_node = Erlang::Cons.allocate
    new_node.instance_variable_set(:@head, list.head)
    new_node.instance_variable_set(:@improper, false)
    tail.instance_variable_set(:@tail, new_node)
    tail.instance_variable_set(:@improper, false)
    tail.immutable!
    tail = new_node
    list = list.tail
    number -= 1
  end
  if not tail.immutable?
    tail.instance_variable_set(:@tail, Erlang::Nil)
    tail.immutable!
  end
  return out.tail
end

#take_while {|item| ... } ⇒ List, Enumerator

Return a List which contains all elements up to, but not including, the first element for which the block returns nil or false.

Examples:

Erlang::List[1, 3, 5, 7, 6, 4, 2].take_while { |e| e < 5 }
# => Erlang::List[1, 3]

Yields:

  • (item)

Returns:

  • (List, Enumerator)

Raises:



285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
# File 'lib/erlang/list.rb', line 285

def take_while(&block)
  raise Erlang::ImproperListError if improper?
  return enum_for(:take_while) unless block_given?
  return self if empty?
  out = tail = Erlang::Cons.allocate
  list = self
  while !list.empty? && yield(list.head)
    new_node = Erlang::Cons.allocate
    new_node.instance_variable_set(:@head, list.head)
    new_node.instance_variable_set(:@improper, false)
    tail.instance_variable_set(:@tail, new_node)
    tail.instance_variable_set(:@improper, false)
    tail.immutable!
    tail = new_node
    list = list.tail
  end
  if not tail.immutable?
    tail.instance_variable_set(:@tail, Erlang::Nil)
    tail.immutable!
  end
  return out.tail
end

#to_proper_listList

Return List with proper ending elemnet Erlang::Nil. If the list is already proper, self is returned.

Returns:



1586
1587
1588
1589
# File 'lib/erlang/list.rb', line 1586

def to_proper_list
  return self if not improper?
  return (self + Erlang::Nil).init
end

#transposeList

Gather the first element of each nested list into a new List, then the second element of each nested list, then the third, and so on. In other words, if each nested list is a "row", return a List of "columns" instead.

Returns:

Raises:



490
491
492
493
494
495
496
497
# File 'lib/erlang/list.rb', line 490

def transpose
  raise Erlang::ImproperListError if improper?
  return Erlang::Nil if empty?
  return Erlang::Nil if any? { |list| list.empty? }
  heads, tails = Erlang::Nil, Erlang::Nil
  reverse_each { |list| heads, tails = heads.cons(list.head), tails.cons(list.tail) }
  return Erlang::Cons.new(heads, tails.transpose)
end

#union(other) ⇒ List Also known as: |

Return a List with all the elements from both this list and other, with all duplicates removed.

Examples:

Erlang::List[1, 2].union(Erlang::List[2, 3]) # => Erlang::List[1, 2, 3]

Parameters:

  • other (List)

    The list to merge with

Returns:

Raises:



750
751
752
753
754
755
756
757
# File 'lib/erlang/list.rb', line 750

def union(other)
  raise Erlang::ImproperListError if improper?
  other = Erlang.from(other)
  raise ArgumentError, "other must be of Erlang::List type" if not Erlang.is_list(other)
  raise Erlang::ImproperListError if other.improper?
  items = ::Set.new
  return _uniq(items).append(other._uniq(items))
end

#uniq(&block) ⇒ List

Return a List with the same items, but all duplicates removed. Use #hash and #eql? to determine which items are duplicates.

Examples:

Erlang::List[:a, :b, :a, :c, :b].uniq      # => Erlang::List[:a, :b, :c]
Erlang::List["a", "A", "b"].uniq(&:upcase) # => Erlang::List["a", "b"]

Returns:



687
688
689
# File 'lib/erlang/list.rb', line 687

def uniq(&block)
  return _uniq(::Set.new, &block)
end

#zip(others) ⇒ List

Combine two lists by "zipping" them together. The corresponding elements from this List and each of others (that is, the elements with the same indices) will be gathered into lists.

If others contains fewer elements than this list, nil will be used for padding.

Examples:

Erlang::List["A", "B", "C"].zip(Erlang::List[1, 2, 3])
# => Erlang::List[Erlang::List["A", 1], Erlang::List["B", 2], Erlang::List["C", 3]]

Parameters:

  • others (List)

    The list to zip together with this one

Returns:

Raises:



460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
# File 'lib/erlang/list.rb', line 460

def zip(others)
  raise Erlang::ImproperListError if improper?
  others = Erlang.from(others)
  raise ArgumentError, "others must be of Erlang::List type" if not Erlang.is_list(others)
  return self if empty? && others.empty?
  out = tail = Erlang::Cons.allocate
  list = self
  until list.empty? or others.empty?
    new_node = Erlang::Cons.allocate
    new_node.instance_variable_set(:@head, Erlang::Cons.new(list.head, Erlang::Cons.new(others.head)))
    new_node.instance_variable_set(:@improper, false)
    tail.instance_variable_set(:@tail, new_node)
    tail.instance_variable_set(:@improper, false)
    tail.immutable!
    tail = new_node
    list = list.tail
    others = others.tail
  end
  if not tail.immutable?
    tail.instance_variable_set(:@tail, Erlang::Nil)
    tail.immutable!
  end
  return out.tail
end