From: ale@... Date: 2001-09-01T18:37:16+09:00 Subject: [ruby-talk:20661] Re: replacing items in arrays Hello Tobias, On Sat, 1 Sep 2001, Tobias Reif wrote: > 1. > why doesn't the second block work? > > line[line_index] = '' + line[line_index] + '' vs. > item = line[line_index] > item = '' + item + '' Well, the reason is the same as with: ruby -e'a=[1,2,3]; b = a[1]; b = 4; p a; a[1] = 4; p a;' [1, 2, 3] [1, 4, 3] The objects for the above are ('->' is a notation for a reference): a -> [-> 1, -> 2, -> 3 ] Statement b = a[1]; b -> 2 (b starts to refer the Fixnum object with content 2 and the object is exactly the same as the one a[1] is referring to) statement b = 4; b -> 4 And when you print array a, it's still an array with element 0 referring to an Fixnum object of 1, element 1 referring to a Fixnum object of 2, and likewise for element 2. Statement a[1] = 4 alters the array to be a -> [-> 1, -> 4, -> 3 ] The first block version first generates a value by '' + a[2] + '' and then says a[2] = new_value, where as the latter block version never alters a[2], thus the table remains the same. Beware there's always danger when you use exclamation-methods, a=["a", "b", "c"]; b = a[1] b.gsub(/b/, "bb") p a b = a[1] b.gsub!(/b/, "bb") p a => ["a", "b", "c"] ["a", "bb", "c"] and one has to be careful even with non-exclamated ones if they clearly alter the state of an object: a = ["a", "b", "c"] b = a[1] b += "b" p a b = a[1] b.concat "b" p a > 2. > wouldn't it be nice to be able to just say: > > Array#replace_each: > ----- > an_array = ['one', 'two'] > > an_array.replace_each do |item| > 'number ' + item > end > ----- > -> ['number one', 'number two'] > > Or did I overlook an equivalent? a = ["one", "two"] a.collect! { |e| "number " + e } p a => ["number one", "number two"] - Aleksi