From: lasitha Date: 2009-02-24T22:27:51+09:00 Subject: Re: Objects put into a declared array Hello dave, On Tue, Feb 24, 2009 at 4:45 PM, Dave Lilley wrote: > > below is a bit of code i've written that creates an array of 25 places. >         @myarray = Array(1..25) While that will indeed create an array of length 25, it does a bit more: $: irb 01> Array(1..4) --> [1, 2, 3, 4] As you can see it also populates the array with each value in the range 1..4. The way the Array method works is to convert its argument (in this case, the Range 1..4) into an array [1]. The simpler way to create an array with 4 'slots' is: 02> Array.new(4) --> [nil, nil, nil, nil] Here's a third way that populates the array with a given object, instead of nil. 03> Array.new(4, 'four') --> ["four", "four", "four", "four"] And this way allows you to fill the array one item at a time by yielding to your block. 04> Array.new(4) {|i| i * i } --> [0, 1, 4, 9] > I then want to "install" a bona fide object like a shape into each 25 > places. > so i do this... >      1.upto @myarray.length do |p| >         @myarray[p] = oval(0,0,20,20) It's best if you can create populated arrays instead of creating then populating them in two steps. The third form i mentioned above will handle most cases. Once you have an array, there are many idiomatic ways to traverse it: $ irb # edited 01> array = [0, 1, 2] 02> array.each {|item| puts item } That's of course the most straightforward. The following creates another array with each item transformed or 'mapped' by the provided block: 03> array.map {|x| x * x } --> [0, 1, 4] That's pretty close to what your code above was doing except that it results in second array. To perform the transformation in place, use #map! [2]. Here's another fun one that i'll let you explore yourself: 04> array.inject(0) {|sum, x| sum += x } --> 3 There are many more, check out the doco on Array and Enumerable. > or can it be @myarray[p] = oval(0,0,20,20).move x,y? Not generally. The whole right-hand-side is evaluated before assignment, so that line would assign the result of the #move method to @my_array[p]. It's possible the #move method returns the object on which it was invoked (self), in which case this would work, but that's a special case. > if i use a local variable when defining ashape and do this >    @myarray[p] << ashape > > then it works without the error that i get presntly which is > > move is private and refers to the actual line @array[p].move = x,y I don't know Shoes, but i'd bet you want that to be @array[p].move(x, y) The way you've got it ruby will look for an attribute writer method[3], #move=, on that object and try to assign the array [x, y] to it. It would be odd to have an attribute named move (since it's a verb) - doesn't sound like something _why would create :). > any explanations would be great and thoughts on best practices with this > sort of thing would be grateful. > > dave. Hope some of that helps. Cheers, lasitha. References: [1] http://ruby-doc.org/core-1.9/classes/Kernel.html#M006081 [2] http://ruby-doc.org/core-1.9/classes/Array.src/M002048.html [3] http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_classes.html#S2