#collect with block modifying receiver

H

Hal Fulton

Hello, all...

I'm wondering what should be the behavior of collect when the block
modifies the receiver.

I don't recall thinking about this before, but I would have said
that the collect always returns as many items as the array had
at the time of the call.

Has this somehow changed since 1.6.*?

The reason I ask is the email (below) I got from Jonathan Lim.
The randomize methods on page 152/153 of _The Ruby Way_ do not
work. It's possible they never did, but I find that hard to
believe.

I don't have an old Ruby around, or I'd test it.

The original line in randomize, of course, read as follows:

arr.collect { arr.slice!(rand arr.length) }

Thanks to you who reply, and thanks again to Jonathan.

Cheers,
Hal


-------- Original Message --------
Subject: Randomizing an Array Errata?
Date: Thu, 28 Aug 2003 15:12:45 +0100
From: Jonathan Lim <[email protected]>
To: (e-mail address removed)

Hi,

On p.153 of the Ruby Way

Should it not read this?

def randomize
arr = self.dup
self.collect { arr.slice!(rand arr.length) }
end

def randomize!
arr = self.dup
result = self.collect { arr.slice!(rand arr.length) }
self.replace result
end

Cheers,
Jon
 
M

mark

Hello, all...

I'm wondering what should be the behavior of collect when the block
modifies the receiver.

I don't recall thinking about this before, but I would have said
that the collect always returns as many items as the array had
at the time of the call.

Has this somehow changed since 1.6.*?

The reason I ask is the email (below) I got from Jonathan Lim.
The randomize methods on page 152/153 of _The Ruby Way_ do not
work. It's possible they never did, but I find that hard to
believe.

I don't have an old Ruby around, or I'd test it.

Running the code from The Ruby Way I get

[mark@laptop mark]$ ruby1.6 -v test.rb
ruby 1.6.7 (2002-03-01) [i586-linux-gnu]
[1, 4, 3, 5, 2]
[4, 5, 2, 3, 1]
[mark@laptop mark]$ ruby -v test.rb
ruby 1.8.0 (2003-08-04) [i686-linux]
test.rb:5: warning: parenthesize argument(s) for future version
test.rb:10: warning: parenthesize argument(s) for future version
[2, 5, 1]
[2, 3, 4]

So it does look like there has been a change between 1.6.7 and 1.8.0

After changing

arr.collect { arr.slice!(rand arr.length) }

to

self.collect { arr.slice!(rand arr.length) }

I get

[mark@laptop mark]$ ruby1.6 -v test.rb
ruby 1.6.7 (2002-03-01) [i586-linux-gnu]
[5, 3, 4, 2, 1]
[2, 1, 3, 5, 4]
[mark@laptop mark]$ ruby -v test.rb
ruby 1.8.0 (2003-08-04) [i686-linux]
[5, 3, 1, 2, 4]
[5, 2, 1, 4, 3]

So this does fix the problem.

Best regards

Mark Sparshatt
 
Y

Yukihiro Matsumoto

Hi,

In message "Re: #collect with block modifying receiver"

|OK, so this *really* makes me wonder what the "theoretically correct"
|behavior is.

|Matz, are you listening?? Enlighten us, please...

Ah, listen, it's undefined behavior. ;-)

To be serious, I don't want to slow down performance by defining any
exact behavior. Don't modify the receiver while you are iterating
over it.

matz.
 
S

Sean O'Dell

Yukihiro said:
Hi,

In message "Re: #collect with block modifying receiver"

|OK, so this *really* makes me wonder what the "theoretically correct"
|behavior is.

|Matz, are you listening?? Enlighten us, please...

Ah, listen, it's undefined behavior. ;-)

To be serious, I don't want to slow down performance by defining any
exact behavior. Don't modify the receiver while you are iterating
over it.

I have to assert my support of this position; modifying a receiver while
in a block would be VERY tedious to anticipate, and would be an endless
source for wonderful new bugs, if the defined behavior were to allow it.

Sean O'Dell
 
H

Hal Fulton

Dan said:
So it's undefined behaviour, but "Don't modify the receiver while you
are iterating over it." :)

Can I suggest the solution that Java uses, which is to fail fast in that
situation (ConcurrentModificationException). You would not believe how
much debugging time that one tiny feature has saved me!

I think throwing an exception falls under "exact behavior." :)
And detecting this situation would be non-trivial, and proabably
not worthwhile anyway. I'm happy enough with the admonition
"Just Don't Do It" (opposite of Nike).

Shame on me for allowing this (pp 152-153) to have found its way
into print.

Hal
 

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,792
Messages
2,569,639
Members
45,353
Latest member
RogerDoger

Latest Threads

Top