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
-
.[](*items) ⇒ List
Create a new
List
populated with the given items. - .compare(a, b) ⇒ Object
-
.empty ⇒ Erlang::List
Return an empty
Erlang::List
.
Instance Method Summary collapse
-
#<<(item) ⇒ List
Create a new
List
withitem
added at the end. -
#add(item) ⇒ List
(also: #cons)
Create a new
List
withitem
added at the front. -
#append(other) ⇒ List
(also: #concat, #+)
Return a
List
with all items from thisList
, followed by all items fromother
. -
#at(index) ⇒ Object
Retrieve the item at
index
. -
#break {|item| ... } ⇒ Array
Return two
List
s, one up to (but not including) the first item for which the block returns true, and another of all the remaining items. -
#chunk(number) ⇒ List
Split the items in this list in groups of
number
. -
#clear ⇒ List
Return an empty
List
. -
#combination(n) ⇒ List
Return a
List
of all combinations of lengthn
of items from thisList
. -
#delete(obj) ⇒ List
Return a
List
with all elements equal toobj
removed. -
#delete_at(index) ⇒ List
Return a
List
containing the same items, minus the one atindex
. -
#drop(number) ⇒ List
Return a
List
containing all items after the firstnumber
items from thisList
. -
#drop_while {|item| ... } ⇒ List, Enumerator
Return a
List
which contains all elements starting from the first element for which the block returnsnil
orfalse
. -
#dup ⇒ List
(also: #clone)
Return
self
. -
#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.
-
#each_chunk(number) {|list| ... } ⇒ self, Enumerator
(also: #each_slice)
Split the items in this list in groups of
number
, and yield each group to the block (as aList
). -
#eql?(other) ⇒ Boolean
(also: #==)
Return true if
other
has the same type and contents as thisHash
. -
#erlang_inspect(raw = false) ⇒ String
Allows this
Map
to be printed usingErlang.inspect()
. -
#fill(obj, index = 0, length = nil) ⇒ List
Replace a range of indexes with the given object.
-
#flat_map(&block) ⇒ List
Return a
List
which is realized by transforming each item into aList
, and flattening the resulting lists. -
#flatten ⇒ List
Return a new
List
with all nested lists recursively "flattened out", that is, their elements inserted into the newList
in the place where the nested list originally was. -
#group_by {|item| ... } ⇒ Map
(also: #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
List
s of items for which the block returned that value. -
#hash ⇒ Integer
See
Object#hash
. -
#indices(object = Erlang::Undefined, i = 0, &block) ⇒ List
Return a
List
of indices of matching objects. -
#init ⇒ List
Return a
List
with all elements except the last one. -
#inits ⇒ List
Return a
List
of all prefixes of this list. -
#insert(index, *items) ⇒ List
Return a new
List
with the given items inserted before the item atindex
. -
#inspect ⇒ ::String
Return the contents of this
List
as a programmer-readableString
. -
#intersperse(sep) ⇒ List
Return a new
List
withsep
inserted between each of the existing elements. -
#last(allow_improper = false) ⇒ Object
Return the last item in this list.
-
#map {|item| ... } ⇒ List, Enumerator
(also: #collect)
Return a
List
in which each element is derived from the corresponding element in thisList
, transformed through the given block. -
#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.
-
#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.
-
#partition {|item| ... } ⇒ Tuple
Return two
List
s, the first containing all the elements for which the block evaluates to true, the second containing the rest. -
#permutation(length = size) {|list| ... } ⇒ self, Enumerator
Yields all permutations of length
n
of the items in the list, and then returnsself
. -
#pop ⇒ List
Return a
List
containing all but the last item from thisList
. -
#reverse ⇒ List
Return a
List
with the same items, but in reverse order. -
#rotate(count = 1) ⇒ List
Return a new
List
with the same elements, but rotated so that the one at indexcount
is the first element of the new list. -
#sample ⇒ Object
Return a randomly chosen element from this list.
-
#select {|item| ... } ⇒ List
(also: #find_all, #keep_if)
Return a
List
which contains all the items for which the given block returns true. -
#slice(arg, length = (missing_length = true)) ⇒ Object
(also: #[])
Return specific objects from the
List
. -
#sort(&comparator) ⇒ List
Return a new
List
with the same items, but sorted. -
#sort_by {|element| ... } ⇒ List
Return a new
List
with the same items, but sorted. -
#span {|item| ... } ⇒ Tuple
Return two
List
s, one up to (but not including) the first item for which the block returnsnil
orfalse
, and another of all the remaining items. -
#split_at(number) ⇒ Tuple
Return two
List
s, one of the firstnumber
items, and another with the remaining. -
#subsequences {|sublist| ... } ⇒ self
Yield every non-empty sublist to the given block.
-
#tails ⇒ List
Return a
List
of all suffixes of this list. -
#take(number) ⇒ List
Return a
List
containing the firstnumber
items from thisList
. -
#take_while {|item| ... } ⇒ List, Enumerator
Return a
List
which contains all elements up to, but not including, the first element for which the block returnsnil
orfalse
. -
#to_proper_list ⇒ List
Return
List
with proper ending elemnetErlang::Nil
. -
#transpose ⇒ List
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. -
#union(other) ⇒ List
(also: #|)
Return a
List
with all the elements from both this list andother
, with all duplicates removed. -
#uniq(&block) ⇒ List
Return a
List
with the same items, but all duplicates removed. -
#zip(others) ⇒ List
Combine two lists by "zipping" them together.
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.
53 54 55 |
# File 'lib/erlang/list.rb', line 53 def self.[](*items) return from_enum(items) end |
.compare(a, b) ⇒ Object
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 |
.empty ⇒ Erlang::List
Return an empty Erlang::List
.
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.
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.
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
.
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
.
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 List
s, one up to (but not including) the first item for which the
block returns true, and another of all the remaining items.
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.
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 |
#clear ⇒ List
Return an empty List
. If used on a subclass, returns an empty instance
of that class.
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
.
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.
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.
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
.
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
.
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 |
#dup ⇒ List Also known as: clone
Return self
. Since this is an immutable object duplicates are
equivalent.
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
.
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
.
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
.
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()
.
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.
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.
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 |
#flatten ⇒ List
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.
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 List
s of items
for which the block returned that value.
964 965 966 |
# File 'lib/erlang/list.rb', line 964 def group_by(&block) return group_by_with(Erlang::Nil, &block) end |
#hash ⇒ Integer
See Object#hash
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.
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 |
#init ⇒ List
Return a List
with all elements except the last one.
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 |
#inits ⇒ List
Return a List
of all prefixes of this list.
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
.
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
.
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.
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.
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
.
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.
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
.
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 List
s, the first containing all the elements for which the
block evaluates to true, the second containing the rest.
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.
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 |
#pop ⇒ List
Return a List
containing all but the last item from this List
.
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 |
#reverse ⇒ List
Return a List
with the same items, but in reverse order.
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.
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 |
#sample ⇒ Object
Return a randomly chosen element from this list.
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.
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.
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 |
#sort ⇒ List #sort {|a, b| ... } ⇒ List
Return a new List
with the same items, but sorted.
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
(#<=>
).
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 List
s, one up to (but not including) the first item for which the
block returns nil
or false
, and another of all the remaining items.
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 List
s, one of the first number
items, and another with the
remaining.
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.)
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 |
#tails ⇒ List
Return a List
of all suffixes of this list.
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
.
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
.
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_list ⇒ List
Return List
with proper ending elemnet Erlang::Nil
.
If the list is already proper, self
is returned.
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 |
#transpose ⇒ List
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.
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.
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.
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.
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 |