Enumerations are not guaranteed length - the only requirement for an object with which Enumerable will enumerate is that it responds with #each , which forces it to return the next element in the series and #<=> #each , which allows you to compare the values ββprovided by an enumerable. Methods like #sort will list the entire collection during sorting, but may not know the boundaries of the set in advance. Consider:
class RandomSizeEnumerable include Enumerable def each value = rand 1000 while value != 500 yield value value = rand 1000 end end
This enumeration will be called until the iterator produces the value "500", which will lead to its reinstallation. The result set is collected and sorted. However, the #length method #length not make sense in this context, since the length is #length until the iterator is exhausted!
We can call #length as a result of things like #sort , since they return an array:
p RandomSizeEnumerable.new.sort.length # 321 p RandomSizeEnumerable.new.sort.length # 227 p RandomSizeEnumerable.new.sort.length # 299
#length is usually used when the length is known and can be returned in constant time, while #count (and sometimes #size ) is usually used when the length can be unknown in advance and needs to be calculated by repeating a set of results (thus taking linear time). If you need the size of the result set provided by Enumerable, try using .to_a.length #count .
source share