array[index,length] strange behaviour

M

Mikel Lindsaar

Hi all,

Running Ruby 1.8.7. And I saw Jim Weirich's post about the Ruby Koans, =
and I thought, what the hey! Lets do them!

So I downloaded, and what do you know! I found something I didn't =
understand!! :)

Anyway, per http://ruby-doc.org/core/classes/Array.html#M002205 it says: =
"Returns nil if the index (or starting index) are out of range".

So given array:

array =3D [:peanut, :butter, :and, :jelly]

One would expect:

array[4] =3D=3D nil #=3D> true
array[5] =3D=3D nil #=3D> true

Which works, 4 and 5 are both out of range.

However:

array[4,0] =3D=3D nil #=3D> false
array[5,0] =3D=3D nil #=3D> true

Huh? In actual fact array[4,0] returns an empty array. This seems in =
conflict with the docs.

Can someone more enlightened please explain?

Thank you!

Mikel
 
R

Rob Biedenharn

Hi all,

Running Ruby 1.8.7. And I saw Jim Weirich's post about the Ruby
Koans, and I thought, what the hey! Lets do them!

So I downloaded, and what do you know! I found something I didn't
understand!! :)

Anyway, per http://ruby-doc.org/core/classes/Array.html#M002205 it
says: "Returns nil if the index (or starting index) are out of
range".

So given array:

array = [:peanut, :butter, :and, :jelly]

One would expect:

array[4] == nil #=> true
array[5] == nil #=> true

Which works, 4 and 5 are both out of range.

However:

array[4,0] == nil #=> false
array[5,0] == nil #=> true

Huh? In actual fact array[4,0] returns an empty array. This seems
in conflict with the docs.

Can someone more enlightened please explain?

Thank you!

Mikel

Well, the docs seem to describe the behavior properly. You have to
read them closely when it says "equal to the array size..." but
Programming Ruby (1.8 and 1.9) have essentially the same text.

Here's a way I've thought about it:

Picture the array with the comma after each element:

[ :peanut, :butter, :and, :jelly, ]

Then the first index is how many commas to skip before starting. So 4
puts your mental cursor after the :jelly, but before the ]

[ :peanut, :butter, :and, :jelly, ]
^
Then you're still "in" the array and take as many elements as
possible. Since there aren't any more, array[4,0] == array[4,1000] == []

When trying to find the starting point for array[5,n], there's no 5th
comma before the ] that ends the array. So you get nil.

It helps me so I hope this description helps you, too!

-Rob

Rob Biedenharn
(e-mail address removed) http://AgileConsultingLLC.com/
(e-mail address removed) http://GaslightSoftware.com/
 
C

Colin Bartlett

[Note: parts of this message were removed to make it a legal post.]

... Anyway, per http://ruby-doc.org/core/classes/Array.html#M002205 it
says: "Returns nil if the index (or starting index) are out of range".
So given array:
array = [:peanut, :butter, :and, :jelly]
One would expect:
array[4] == nil #=> true
array[5] == nil #=> true
Which works, 4 and 5 are both out of range.
However:
array[4,0] == nil #=> false
array[5,0] == nil #=> true
Huh? In actual fact array[4,0] returns an empty array. This seems in
conflict with the docs.
Can someone more enlightened please explain?

As well as Rob's reply there is this recent thread, which has an explanation
from Matz:

http://groups.google.com/group/comp.lang.ruby/browse_thread/thread/f09c65251c72ab6/9a125107e3186534

extracts:
http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/368268
... So, to summarize, when indexing a position beyond the length of a
string, ruby returns nil. But when indexing a slice beyond the length
of a string, ruby returns an empty string "" for the first index
beyond and then nil.

I don't like that this passes
assert "foo"[3] != "foo"[3,1] ...

http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/368271
"foo"[3,1] is "" since when index is within the string, the sought
length will be rounded to fit in the size. And 3 (which equals to the
length of the string) is considered as touching the end of the string,
so the result length is zero. ... matz.

... Here's a way I've thought about it:
Picture the array with the comma after each element ...

That may - or may not! - explain this behaviour: I've been wondering why the
statements with 1 (but not 2) 'superfluous' commas at the end don't give a
syntax error:
arr = [] #=> []
arr = [ 0 ] #=> [0]
arr = [ 0, ] #=> [0]; superfluous comma is ignored
arr = [ 0, 1, 2 ] #=> [0, 1, 2]
arr = [ 0, 1, 2, ] #=> [0, 1, 2]; superfluous comma is ignored
but these give: syntax error, unexpected ',', expecting ']'
# arr = [ 0, 1, 2, 3,, ]
# arr = [ , ]
 
R

Rob Biedenharn

... Here's a way I've thought about it:
Picture the array with the comma after each element ...

That may - or may not! - explain this behaviour: I've been wondering
why the
statements with 1 (but not 2) 'superfluous' commas at the end don't
give a
syntax error:
arr = [] #=> []
arr = [ 0 ] #=> [0]
arr = [ 0, ] #=> [0]; superfluous comma is ignored
arr = [ 0, 1, 2 ] #=> [0, 1, 2]
arr = [ 0, 1, 2, ] #=> [0, 1, 2]; superfluous comma is ignored
but these give: syntax error, unexpected ',', expecting ']'
# arr = [ 0, 1, 2, 3,, ]
# arr = [ , ]


Well, given that Matz is a C programmer (as was I), he may have wanted
to allow:

<code lang="ruby">
arr = [
0,
1,
2,
3,
]
</code>

When making C array literals, I would often do:

<code lang="C">
int arr[] = {
0
,1
,2
,3
};
</code>

because it was much more likely to add another element to the end than
to the beginning of the array. In C, you couldn't have a trailing
comma and in ruby, there has to be something to clue the parser into
the fact that there's more to come on the next line.

-Rob

Rob Biedenharn
(e-mail address removed) http://AgileConsultingLLC.com/
(e-mail address removed) http://GaslightSoftware.com/
 
C

Christopher Dicely

... Anyway, per http://ruby-doc.org/core/classes/Array.html#M002205 it
says: =C2=A0"Returns nil if the index (or starting index) are out of ran= ge".
So given array:
=C2=A0array =3D [:peanut, :butter, :and, :jelly]
One would expect:
=C2=A0array[4] =3D=3D nil #=3D> true
=C2=A0array[5] =3D=3D nil #=3D> true
Which works, 4 and 5 are both out of range.
However:
=C2=A0array[4,0] =3D=3D nil #=3D> false
=C2=A0array[5,0] =3D=3D nil #=3D> true
Huh? =C2=A0In actual fact array[4,0] returns an empty array. =C2=A0This = seems in
conflict with the docs.
Can someone more enlightened please explain?

As well as Rob's reply there is this recent thread, which has an explanat= ion
from Matz:

http://groups.google.com/group/comp.lang.ruby/browse_thread/thread/f09c65= 251c72ab6/9a125107e3186534

extracts:
http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/368268
... So, to summarize, when indexing a position beyond the length of a
string, ruby returns nil. But when indexing a slice beyond the length
of a string, ruby returns an empty string "" for the first index
beyond and then nil.

I don't like that this passes
assert "foo"[3] !=3D "foo"[3,1] ...

Strings are weird because they act like a container where the
individual contained items look like length 1 slices, which can create
an expectation that indexing and length-1 slices with the same base
index would be the identical. But the behavior makes sense when you
think about slicing (as opposed to simple indexing) as an operation on
a container that returns a container, while indexing is an operation
on a container that returns an element.

There's no reason to expect an equivalency between the element
returned by container[3] indexing and the container returned by
container[3,1] slicing. You should expect that the first element
(index of 0) in the container returned by the slicing would be the
same as the element returned by the indexing, and with Ruby's existing
behavior for both Arrays and Strings where slicing out of range
returns an empty container of the same kind you sliced, that works.

container[3] =3D=3D container[3,1][0]

whether container is "foo", [:f,:eek:,:eek:], "foobar", or [1,2,3,4,5]

If Ruby returned nil rather than an empty container from slicing past
the end of the container, than, for containers with length of 3 or
less, the counter intuitive result would be:

counter[3] !=3D container[3,1][0]
 
R

Rick DeNatale

As well as Rob's reply there is this recent thread, which has an explanati> from Matz:

http://groups.google.com/group/comp.lang.ruby/browse_thread/thread/f09c65251c72ab6/9a125107e3186534

Which includes this gem:

"And a tip for you; never mention PoLS again to persuade me. It's no
use. If you have real trouble besides misunderstanding, let me know.
matz. "

I've long felt that the problem with the principle of least surprise
is that what's surprising is inherently subjective. One man's obvious
is another's surprise.

--
Rick DeNatale

Blog: http://talklikeaduck.denhaven2.com/
Github: http://github.com/rubyredrick
Twitter: @RickDeNatale
WWR: http://www.workingwithrails.com/person/9021-rick-denatale
LinkedIn: http://www.linkedin.com/in/rickdenatale
 

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

Similar Threads

Help with array 1
[ANN] rs 0.1.2 0
Array Slicing 1.9.2 1
MiniQuiz : Renesting Nodes (OWLScratch) 1
safe array index ? 12
First Ruby Program 3
Array#slice! bug? 0
Index Array (Yet Another Question) 0

Members online

No members online now.

Forum statistics

Threads
473,995
Messages
2,570,236
Members
46,825
Latest member
VernonQuy6

Latest Threads

Top