unexpected behavior of range.each (Newbie extreme)

J

Joe Percival

with r=(5..9), r.each{|num| print num,"\n"} behaves as expected.

However if i set r=(9..5) the same method does not behave as though it
were taking "each" element of the range. It just terminates. Not only
that but r.include?(7) is false???

Is this a bug or was it done on purpose for some reason? Are range
specifications only allowed to be "low to high" if so, why? Also if
so, then why no error message and why does r = (9..5)?

Thanks in advance!
joe
 
G

Gary Wright

It was done on purpose. Ranges want to be able to iterate from
beginning to end using the .succ method on the objects that the
range is constructed from. That's not possible for (9..5). Also,
the definition for .include? is range.start <= val <= range.end.
Not true for (9..5).

There have been several threads over the last few months
regarding the peculiarities of Ranges. The semantics seem
a bit confused. Sometimes ranges behave like generated sequences
of objects, sometimes they behave like intervals, and sometimes
they just behave like a coordinate pair. The behavior also depends
quite a bit on the objects used to construct the range.

They are quite convenient in any number of situations but they
have some rough edges. Is it worth trying to craft an RCR that
smooths things out a bit?

Gary Wright
 
J

Joe Percival

Timothy said:
It was done on purpose. Ranges want to be able to iterate from beginning
to end using the .succ method on the objects that the range is
constructed from. That's not possible for (9..5). Also, the definition
for .include? is range.start <= val <= range.end. Not true for (9..5).

seems like an odd definition of "include" (and "each") and inconsistent
with the behavior for arrays. Also, if (9..5) is not a valid range
specification why no error message?
It seems to me that the definition of include (and each) for a range
could be made a bit more tollerant of direction by making it conditional
on the order of the endpoints. Ahh...Well... guess I ought to stop
complaining and just go back to learning the language :)

Thanks for the explanation!
joe
 
J

James H.

Hey Joe (Whatcha doin' with that gun in your hand? -- a little Jimi
Hendrix for you)

Someone might have a better answer than me, but I'll give it a shot.

The answer to your question is yes, this is intended behavior. Let's
look at the Ruby documentation for Range#each:

"Iterates over the elements rng, passing each in turn to the block. You
can only iterate if the start object of the range supports the succ
method (which means that you can't iterate over ranges of Float
objects).", http://www.ruby-doc.org/core/classes/Range.html#M001156

Basically, when r = (9..5), you're first saying: 9#succ, which returns
10. 10's outside of your Range which tells #each to stop.

So, yes: "low to high". I'm not sure, however, why there's no error
message.

I hope you found this helpful.

James
 
G

George Ogata

Joe Percival said:
seems like an odd definition of "include" (and "each") and inconsistent
with the behavior for arrays. Also, if (9..5) is not a valid range
specification why no error message?

You can't error on construction simply because end < start. Consider:

str[2..-1]
It seems to me that the definition of include (and each) for a range
could be made a bit more tollerant of direction by making it conditional
on the order of the endpoints. Ahh...Well... guess I ought to stop
complaining and just go back to learning the language :)

You could make Ranges go backwards, but that changes the soul of the
ruby Range. (Confusion and code breakage everywhere.) I think having
backwards ranges do nothing can also have its uses, though I can't
conjure up a convincing one on the spot.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,483
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top