lib/linked/list.rb in linked-0.2.1 vs lib/linked/list.rb in linked-0.3.0
- old
+ new
@@ -60,28 +60,28 @@
source.each_item { |item| push item.dup }
super
end
-
+
# Identity method that simply return the list. This method mirrors Item#list
# and allows other methods that work on List objects to easily and
# interchangebly accept both lists and items as arguments.
#
# Returns the list itself.
-
+
def list
self
end
-
+
# Access the first item in the list. If the list is empty a NoMethodError
# will be raised. This mirrors the behaviour of Item#item and allows other
# methods that work on List objects to easily and interchangeably accept
# both lists and items as arguments.
#
# Returns the first item in the list.
-
+
def item
raise NoMethodError if empty?
eol.next
end
@@ -165,22 +165,22 @@
def empty?
@item_count == 0
end
- # Insert an item at the end of the list. If the given object is not an Item,
- # or a decendant of Item, it will be treated as a value. Depending on the
- # state of the list the value will be
- # a) wraped in a new instance of Item if the list is empty or
- # b) wraped in an object of the same class as the last item in the list.
+ # Insert an item at the end of the list. If the given object is not an
+ # object responding to #item it will be treated as a value. The value will
+ # be wraped in a new Item create by #create_item.
#
- # item - the item to insert, or an arbitrary value.
+ # See Item#append for more details.
#
+ # object - the item to insert, or an arbitrary object.
+ #
# Returns self.
- def push(item)
- eol.append item
+ def push(object)
+ eol.append object
self
end
alias << push
@@ -192,21 +192,21 @@
return nil if empty?
last.delete
end
# Insert an item at the beginning of the list. If the given object is not an
- # Item, or a decendant of Item, it will be treated as a value. Depending on
- # the state of the list the value will be
- # a) wraped in a new instance of Item if the list is empty or
- # b) wraped in an object of the same class as the last item in the list.
+ # object responding to #item it will be treated as a value. The value will
+ # be wraped in a new Item create by #create_item.
#
- # item - the item to insert, or an arbitrary value.
+ # See Item#prepend for more details.
#
+ # object - the item to insert, or an arbitrary object.
+ #
# Returns self.
- def unshift(item)
- eol.prepend item
+ def unshift(object)
+ eol.prepend object
self
end
# Shift the first item off the list.
#
@@ -214,36 +214,28 @@
def shift
return nil if empty?
first.delete
end
-
+
# Check if an item is in the list.
#
# item - Item, or any object that may be in the list.
#
# Returns true if the given item is in the list, otherwise false.
-
+
def include?(item)
item.in? self
rescue NoMethodError
false
end
- # Iterates over each item in the list, either in normal or reverse order. If
- # a block is not given an enumerator is returned.
- #
- # reverse - flips the iteration order if true. Note that this option is
- # depricated and will be removed in the next major release.
+ # Iterates over each item in the list If a block is not given an enumerator
+ # is returned.
- def each_item(reverse: false, &block)
- if reverse
- warn '[DEPRECATION] the option `reverse: true` will be removed in a future release. Please call `reverse_each_item` instead.'
- eol.before(&block)
- else
- eol.after(&block)
- end
+ def each_item(&block)
+ eol.after(&block)
end
alias each each_item
# Iterates over each item in the list in reverse order. If a block is not
@@ -283,10 +275,24 @@
end
res.join("\n")
end
+ # Protected factory method for creating items compatible with the list. This
+ # method is called whenever an arbitrary object is pushed or unshifted onto
+ # the list and need to be wraped inside an Item.
+ #
+ # This method can be overridden to suport different Item types.
+ #
+ # args - any arguments will be passed on to Item.new.
+ #
+ # Returns a new Item.
+
+ protected def create_item(*args)
+ Item.new(*args)
+ end
+
# Internal method to grow the list with n elements. Never call this method
# without also inserting the n elements.
#
# n - the number of items that has been/will be added to the list.
#
@@ -304,21 +310,21 @@
# Returns updated the item count.
private def shrink(n = 1)
@item_count -= n
end
-
+
# Private method to clear the list. Never call this method without also
# modifying the items in the list, as this operation leavs them in an
# inconsistant state. If the list items are kept, make sure to
# a) clear the `prev` pointer of the first item and
# b) clear the `next` pointer of the last item.
-
+
private def clear
head.send :next=, tail
tail.send :prev=, head
-
+
@item_count = 0
end
# Protected helper method that returns the first n items, starting just
# after item, given that there are items_left items left. Knowing the exact
@@ -340,11 +346,11 @@
protected def first_item_after(item, n, items_left = @item_count)
# Optimize for these cases
return nil if n == 0
return n > 1 ? [] : nil if item.next!.nil?
return item.next if n == 1
-
+
n = items_left if n > items_left
arr = Array.new n
n.times { |i| arr[i] = item = item.next }
arr
@@ -374,21 +380,21 @@
return nil if n == 0
return n > 1 ? [] : nil if item.prev!.nil?
return item.prev if n == 1
n = items_left if n > items_left
-
+
arr = Array.new n
(n - 1).downto(0) { |i| arr[i] = item = item.prev }
arr
rescue StopIteration
arr.compact! || arr
end
-
+
# This method is called whenever the module is included somewhere. In the
# special case when List is included in an Item the #item method must be
# changed to return self.
-
+
def self.included(klass)
klass.send(:define_method, :item) { self } if klass < Item
end
end
end