C
Clifford Heath
Folk,
I found Sean Russell's 2001 posting on this subject, and had a play with creating
open ranges using of class instances - interesting to find you can even do this!
What I really want is to be able to define ranges like (1..nil), which is an
open-ended range starting from 1. Of course this doesn't work, but not for the
reason I expected. There seems to be some magic inside MRI that prevents it.
Like if I define:
class End
attr_reader :e
def initialize(e)
@e = e
end
def <=>(other)
@e <=> other.e
end
def succ
@e && @e.succ
end
end
Then I can create the following range: End.new(1) .. End.new(4)
but not this: End.new(1) .. End.new(nil)
Ok, perhaps that's fair enough. But inside class End, replace all
references to @e by @e.to_i (just for the experiment), and it works
(at least, it bitches that 0 is less than 1, but use
End.new(-1) .. End.new(nil)
and it's ok).
Now add puts "#{@e.to_i} <=> #{other.e}"; into the "<=>" method, and
Range "knows" that's not ok... when to my mind it should be ok if the
previous version was.
I haven't taken this any further yet. Until I know that some internal
magic isn't going to stop me making a Range class that works as advertised,
it didn't seem worth pursuing.
What do you think?
Clifford Heath.
I found Sean Russell's 2001 posting on this subject, and had a play with creating
open ranges using of class instances - interesting to find you can even do this!
What I really want is to be able to define ranges like (1..nil), which is an
open-ended range starting from 1. Of course this doesn't work, but not for the
reason I expected. There seems to be some magic inside MRI that prevents it.
Like if I define:
class End
attr_reader :e
def initialize(e)
@e = e
end
def <=>(other)
@e <=> other.e
end
def succ
@e && @e.succ
end
end
Then I can create the following range: End.new(1) .. End.new(4)
but not this: End.new(1) .. End.new(nil)
Ok, perhaps that's fair enough. But inside class End, replace all
references to @e by @e.to_i (just for the experiment), and it works
(at least, it bitches that 0 is less than 1, but use
End.new(-1) .. End.new(nil)
and it's ok).
Now add puts "#{@e.to_i} <=> #{other.e}"; into the "<=>" method, and
Range "knows" that's not ok... when to my mind it should be ok if the
previous version was.
I haven't taken this any further yet. Until I know that some internal
magic isn't going to stop me making a Range class that works as advertised,
it didn't seem worth pursuing.
What do you think?
Clifford Heath.