Question about behavior of Array.new

Hi,

I recently used the following in a program (game) I’m working on:

board = Array.new(9,Space.new)

I found out at this point, and with a bit of searching in the ruby.lang
archives, that this winds up creating an array with nine references to the
same object. So, now knowing that this happens, I can deal with it, but
what I want to know is WHY it’s like this. Perhaps it’s just the way my
mind works, but to me, this kind of goes against the “least surprise” ethic
of ruby. I, personally, would expect that this would create nine new
objects, not references to the same object.

Can anyone enlighten me on this?

Thanks,
Jeremy

I recently used the following in a program (game) I’m working on:

board = Array.new(9,Space.new)

Can anyone enlighten me on this?

···

----- Original Message -----
From: “Jeremy” thinker5555@yahoo.com


What you are doing is the same as this:

justOneSpace = Space.new
board = Array.new(9,justOneSpace)

Make more sense now? You weren’t passing in the code `Space.new’, just
the object it returned. If you want to pass in the code, use a block:

board = Array.new(9) {Space.new}

That was a good question. Maybe I should put this in my tutorial.

Chris

I found out at this point, and with a bit of searching in the ruby.lang
archives, that this winds up creating an array with nine references to the
same object. So, now knowing that this happens, I can deal with it, but
what I want to know is WHY it's like this.

How do you create these 9 objects from one object ?

and don't reply #dup because in some special case it can be
inappropriated :slight_smile:

1.8 has a new syntax where Array::new accept a block to do what you want

pigeon% ruby -ve 'p Array.new(2) { Object.new }'
ruby 1.8.0 (2003-03-23) [i686-linux]
[#<Object:0x401ac424>, #<Object:0x401ac410>]
pigeon%

*warning* it don't work with 1.6.8

pigeon% /usr/bin/ruby -ve 'p Array.new(2) { Object.new }'
ruby 1.6.8 (2002-12-24) [i686-linux]
[nil, nil]
pigeon%

Guy Decoux

for 1.6.x you can do something like this :

----CUT----
class Array
def Array.init(size = 0, object = nil)
a = Array.new(size, object)
size.times {|i| a[i] = yield(i)} if block_given?
return a
end
end

a = Array.init(1, 42)
p a

a = Array.init(3){|i| i}
p a

answer = ‘enqsxsvn’
a = Array.init(answer.size){|c| (answer[c] + 1).chr}
p a.join
----CUT----

-a

···

On Sun, 23 Mar 2003, Jeremy wrote:

Can anyone enlighten me on this?

Ara Howard
NOAA Forecast Systems Laboratory
Information and Technology Services
Data Systems Group
R/FST 325 Broadway
Boulder, CO 80305-3328
Email: ahoward@fsl.noaa.gov
Phone: 303-497-7238
Fax: 303-497-7259
====================================

A common idiom applied to this case yields:

board = (0…9).map { Space.new }

I think this is covered in the newcomers’ list. Check it out (in the
documentation bundle at www.ruby-doc.org) for other gotchas.

Gavin

···

On Monday, March 24, 2003, 4:12:39 AM, Jeremy wrote:

Hi,

I recently used the following in a program (game) I’m working on:

board = Array.new(9,Space.new)

EHLO

  • On 2003-03-23 18:53
···

board = Array.new(9,Space.new)

this kind of goes against the “least surprise” ethic of ruby.

You generate a new Space object and then use that object to
initialize an Array object. Could do you expect this to result in
and why that result would be less surprising?

Besides that: Least surprise does not mean no surprise at all.

Josef ‘Jupp’ Schugt http://jupp.tux.nu jupp(AT)gmx(DOT)de

Mankind must put an end to war before war puts an end to mankind.
– John F. Kennedy

Gavin Sinclair wrote:

···

On Monday, March 24, 2003, 4:12:39 AM, Jeremy wrote:

Hi,

I recently used the following in a program (game) I’m working on:

board = Array.new(9,Space.new)

A common idiom applied to this case yields:

board = (0…9).map { Space.new }

I think this is covered in the newcomers’ list. Check it out (in the
documentation bundle at www.ruby-doc.org) for other gotchas.

Thank you for pointing out the documentation bundle at ruby-doc.org. I now
have that one sitting happily on my hard drive.

On a broader note, I appreciate everybody’s response on this subject. These
have been good suggestions on working with this “gotcha”. Thanks for the
help.

Jeremy

Gavin Sinclair gsinclair@soyabean.com.au wrote in message news:125-2007456129.20030324132059@soyabean.com.au

A common idiom applied to this case yields:

board = (0…9).map { Space.new }

Presumably

board = Array(10).map! { Space.new }

is better? map doesn’t know how many objects the Range’s each method
will return so it creates an empty array and repeatedly pushes objects
onto it. Explicitly calling Array.new creates the right size array
immediately – much more efficient (not that it matters for one-off
creations with so few elements).

Tom