Ruby introduced Endless Range in Ver.2.6 and Beginless in Ver.2.7.
I expect the sizes of endless/beginless or beginless Ranges are always infinite (Float::INFINITY
), considering "endless" and beginless are (I interpret as) abstract terms.
However, I realise the size of (only) the endless Range of String is nil
(see the last line of the example below), whereas the sizes of (..nil)
, endless/beginless Numeric Ranges, and even beginless String Ranges are Infinity.
(..nil).size # => Float::INFINITY
(..3).size # => Float::INFINITY
(3..).size # => Float::INFINITY
(..?a).size # => Float::INFINITY
(?a..).size # => nil(!)
In fact, I find that it (= the behaviour for the String class) is the case for an arbitrary user-defined class.
class MyC
def succ
end
end
(..MyC.new).size # => Float::INFINITY
(MyC.new..).size # => nil(!)
Why is it so?
How can I make (MyC.new..).size
return Float::INFINITY
, in the same way as (..MyC.new).size
and (..3).size?
I suppose I could redefine Range#size
, maybe in combinatin with refine
and using
, but it seems to me like a dirty hack……
Note all tests above were run with Ruby-3.1.2p20.
CodePudding user response:
Range#size
says...
Returns the count of elements in self if both begin and end values are numeric; otherwise, returns nil
Which means (?a..).size
is nil
as expected, but (..?a).size
should also be nil
yet it isn't.
Even if one follows the example from the documentation it is still nil
.
class Xs
include Comparable
attr_accessor :length
def initialize(n)
@length = n
end
def succ
Xs.new(@length 1)
end
def <=>(other)
@length <=> other.length
end
def to_s
sprintf "- #{inspect}", @length
end
def inspect
'X' * @length
end
end
p (..Xs.new(5)).size # => Float::INFINITY
p (Xs.new(5)..).size # => nil(!)
The size
documentation and implementation may need to be updated in light of beginless and endless Ranges. This might be a candidate for a bug report.