Question: arrays v. ranges and *.each

D

David Douthitt

The results of the following code just seem strange to me:

print "\nTry 1:"
print [1..10].class, "\n"
[1..10].each { |x| print x, "\n" }

print "\nTry 2:"
print [1..10].pop.class, "\n"
[1..10].pop.each { |x| print x, "\n" }

I would have thought that either 1) try 1 would output a sequence of
numbers, and try 2 would result in an error (no such method
Integer#each); or, 2) try 1 would output a series of numbers and try 2
would result in an error (no such method Range#pop). Perhaps - another
option would be 3) try 1 would result in '1..10' and try 2 would result
in something like '1..1' or an error?

I'm confused...
 
J

Jason Foreman

The results of the following code just seem strange to me:
=20
print "\nTry 1:"
print [1..10].class, "\n"
[1..10].each { |x| print x, "\n" }
=20
print "\nTry 2:"
print [1..10].pop.class, "\n"
[1..10].pop.each { |x| print x, "\n" }
=20
I would have thought that either 1) try 1 would output a sequence of
numbers, and try 2 would result in an error (no such method
Integer#each); or, 2) try 1 would output a series of numbers and try 2
would result in an error (no such method Range#pop). Perhaps - another
option would be 3) try 1 would result in '1..10' and try 2 would result
in something like '1..1' or an error?
=20
I'm confused...

the .. operator does not output a series of numbers, but rather an
instance of the class Range.

Try 1 is an array with a single element, a Range object. Calling each
on the array yields each element, in this case the single Range
object, and you've output it to the console, which gives "1..10" which
is how the Range responds to to_s.

Try 2 is the same array. You pop the first element, which is the
Range object, and call each, which iterates over the numbers
represented by the range.

Try this:
(1..10).entries

That gives you an array of all the elements represented by the Range.


Jason
 
S

Shashank Date

Hi David,

--- David Douthitt said:
The results of the following code just seem strange to me:
=20
print "\nTry 1:"
print [1..10].class, "\n"
[1..10].each { |x| print x, "\n" }

You are mixing two things here: a range and an array.
[1..10] is an array of one object (1..10) which is an
instance of the Range class.=20
print "\nTry 2:"
print [1..10].pop.class, "\n"
[1..10].pop.each { |x| print x, "\n" }

so [1..10].pop gives (1..10).

And Range itself is Enumerable.

so: (1..10).each {|i| p i} is a valid construct.

I would have thought that either 1) try 1 would output a sequence of
numbers, and try 2 would result in an error (no such method
Integer#each); or, 2) try 1 would output a series of numbers and try 2
would result in an error (no such method Range#pop). Perhaps - another
option would be 3) try 1 would result in '1..10' and try 2 would result
in something like '1..1' or an error?
=20
I'm confused...

HTH,
-- shanko


=09
____________________________________________________
Sell on Yahoo! Auctions =96 no fees. Bid on great items. =20
http://auctions.yahoo.com/
 
J

James Edward Gray II

The results of the following code just seem strange to me:

print "\nTry 1:"
print [1..10].class, "\n"

[ ... ] builds an Array. 1..10 builds a Range. So Ruby sees this as
an Array with a single member, a Range.

As an aside, you should look into puts():

puts [1..10].class # no newline needed!
[1..10].each { |x| print x, "\n" }

So here we are printing the one member, the Range.
print "\nTry 2:"
print [1..10].pop.class, "\n"

Here we remove the Array's one member (again a Range) and show its
class.
[1..10].pop.each { |x| print x, "\n" }

Again, printing the one popped member.

Now all of that discusses what you showed, not what you meant. Let's
talk about that.

It seems to me you are trying to treat a Range as an Array. The
first thing to know there is that Ranges are already Enumerable:

irb(main):006:0> (1..10).each { |n| puts n }
1
2
3
4
5
6
7
8
9
10
=> 1..10

The other fact that may be of use to you is that we can turn a Range
into an Array, as needed:

irb(main):007:0> ("a".."j").to_a
=> ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j"]

Hope that clears some things up.

James Edward Gray II
 
D

Daniel Brockman

David Douthitt said:
The results of the following code just seem strange to me:

print "\nTry 1:"
print [1..10].class, "\n"
[1..10].each { |x| print x, "\n" }

print "\nTry 2:"
print [1..10].pop.class, "\n"
[1..10].pop.each { |x| print x, "\n" }

I would have thought that either 1) try 1 would output a sequence of
numbers, and try 2 would result in an error (no such method
Integer#each); or, 2) try 1 would output a series of numbers and try 2
would result in an error (no such method Range#pop). Perhaps - another
option would be 3) try 1 would result in '1..10' and try 2 would result
in something like '1..1' or an error?

I'm confused...

Well, `a..b' is a range and `[foo]' is an array of one element, so
rather naturally `[a..b]' is an array containing one element: a range.

You can get an array from a range by doing `(a..b).to_a'.

print "\nTry 2:"
print (1..10).to_a.pop.class, "\n"
(1..10).to_a.pop.each { |x| print x, "\n" }

Of course, ranges are already enumerable, so this works OK:

print "\nTry 1:"
print (1..10).class, "\n"
(1..10).each { |x| print x, "\n" }
 
D

David Douthitt

Shashank said:
You are mixing two things here: a range and an array.
[1..10] is an array of one object (1..10) which is an
instance of the Range class.

Aha! That explains it all... So then:

puts ([1..10] == 1..10 ? "true" : "false")

returns "false" - a complicated way to say 1..10 and [1..10] are not
the same thing :)

So, in my original programming, what I wanted was not "[1..10]" but
"(1..10)". It all makes sense now.

Thanks all!
 
J

Joe Van Dyk

Shashank Date wrote:
=20
You are mixing two things here: a range and an array.
[1..10] is an array of one object (1..10) which is an
instance of the Range class.
=20
Aha! That explains it all... So then:
=20
puts ([1..10] =3D=3D 1..10 ? "true" : "false")
=20
returns "false" - a complicated way to say 1..10 and [1..10] are not
the same thing :)
=20
So, in my original programming, what I wanted was not "[1..10]" but
"(1..10)". It all makes sense now.

Don't feel bad... this tripped me up as well too.
 

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
474,175
Messages
2,570,944
Members
47,491
Latest member
mohitk

Latest Threads

Top