Why doesn't "to_s" DWIM?

How come to_s doesn't work here?

···

####################################
require 'test/unit'
class TOY_CASE<Test::Unit::TestCase

def test_toy_test

aoa = [[1,2,3],[4,5,6]]

aoa.each do |arr|
  arr.each do |item|
    item = item.to_s
    end
    assert_equal(["1","2","3"],arr)
end

end #def
end #class
##########################################

Hi --

How come to_s doesn't work here?

####################################
require 'test/unit'
class TOY_CASE<Test::Unit::TestCase

def test_toy_test

aoa = [[1,2,3],[4,5,6]]

aoa.each do |arr|
  arr.each do |item|
    item = item.to_s
    end
    assert_equal(["1","2","3"],arr)
end

end #def
end #class
##########################################

Inside the inner each block, you're just doing a local (re)assignment
to "item". There's no connection to the object that used to be in
item, except that that object happens to be part of the rhs.

You can achieve what you want with this:

   aaa.each do |arr|
     arr.map! do |item|
       item.to_s
     end
   end

That will go through each inner array and replace the current item
with what's in the block (namely, item.to_s).

David

···

On Thu, 23 Mar 2006, Chris McMahon wrote:

--
David A. Black (dblack@wobblini.net)
Ruby Power and Light, LLC (http://www.rubypowerandlight.com)

"Ruby for Rails" chapters now available
from Manning Early Access Program! Ruby for Rails

You might want to look at Array#map

arr.map do |item|
  item.to_s
end

···

On 3/22/06, Chris McMahon <christopher.mcmahon@gmail.com> wrote:

How come to_s doesn't work here?

####################################
require 'test/unit'
class TOY_CASE<Test::Unit::TestCase

def test_toy_test

aoa = [[1,2,3],[4,5,6]]

aoa.each do |arr|
        arr.each do |item|
                item = item.to_s
                end
                assert_equal(["1","2","3"],arr)
end

end #def
end #class
##########################################

Each just iterates the items, and the 'items' argument to the block is a
new local variable - changing it has no lasting effect. Try map instead
(here I use map! to change this array, rather than creating a new one):

···

On Thu, 2006-03-23 at 01:18 +0900, Chris McMahon wrote:

How come to_s doesn't work here?

####################################
require 'test/unit'
class TOY_CASE<Test::Unit::TestCase

def test_toy_test

aoa = [[1,2,3],[4,5,6]]

aoa.each do |arr|
  arr.each do |item|
    item = item.to_s
    end
    assert_equal(["1","2","3"],arr)
end

end #def
end #class
##########################################

##########################################
require 'test/unit'
class TOY_CASE<Test::Unit::TestCase

  def test_toy_test

    aoa = [[1,2,3],[4,5,6]]

    aoa.each do |arr|
      arr.map! do |item|
        item.to_s
      end
    end

    assert_equal [["1","2","3"],["4","5","6"]], aoa
  end #def
end #class
##########################################

Notice too I changed the way your assertion works, since it would fail
on the second array if tested against ["1","2","3"].

--
Ross Bamford - rosco@roscopeco.REMOVE.co.uk

I'm not really sure what you are expecting to happen here. aoa.each will product two results, first [1,2,3] and then [4,5,6]. And you expect the assert_equal to pass both times?

Thanks, I knew it had to be something like that.

aoa = [[1,2,3],[4,5,6]]

aoa.each do |arr|
arr.each do |item|
item = item.to_s
end
assert_equal(["1","2","3"],arr)
end

end #def
end #class
##########################################

Each just iterates the items, and the 'items' argument to the block is a
new local variable - changing it has no lasting effect.

but remember:

a = ["haha", "hihi", "hoho"]
a.each { |i| i.gsub!("h", "l") }
p a

and even

a = ["2","3", "4"]
a.each { |i| i.replace("#{i} times") }
p a

in fact variables only point to the objects. so you might use them to modify
the object they are currently pointing to. if you got strings, you may
modify them (instead of creating new ones). but unfortunately that won't
work for numbers, since they are no real objects, but - how do we call
them? - first level objects?

benny

···

Try map instead
(here I use map! to change this array, rather than creating a new one):

##########################################
require 'test/unit'
class TOY_CASE<Test::Unit::TestCase

  def test_toy_test

    aoa = [[1,2,3],[4,5,6]]

    aoa.each do |arr|
      arr.map! do |item|
        item.to_s
      end
    end

    assert_equal [["1","2","3"],["4","5","6"]], aoa
  end #def
end #class
##########################################

Notice too I changed the way your assertion works, since it would fail
on the second array if tested against ["1","2","3"].

benny wrote:

a = ["2","3", "4"]
a.each { |i| i.replace("#{i} times") }
p a

in fact variables only point to the objects. so you might use them to
modify the object they are currently pointing to. if you got strings, you
may modify them (instead of creating new ones). but unfortunately that
won't
work for numbers, since they are no real objects, but - how do we call
them? - first level objects?

so this would work also:

aoa = [[1,2,3],[4,5,6]]

aoa.each do |arr|
  arr.each_index do |i|
    arr[i] = arr[i].to_s
  end
end

p aoa

···

benny

True, this is why the updated code I and others posted mostly retained
the outer 'each', and used map! on each inner array.

I think the term for Fixnums, nil, true and false is 'immediate values'.

···

On Thu, 2006-03-23 at 05:28 +0900, benny wrote:

>> aoa = [[1,2,3],[4,5,6]]
>>
>> aoa.each do |arr|
>> arr.each do |item|
>> item = item.to_s
>> end
>> assert_equal(["1","2","3"],arr)
>> end
>>
>>
>> end #def
>> end #class
>> ##########################################
>
> Each just iterates the items, and the 'items' argument to the block is a
> new local variable - changing it has no lasting effect.
but remember:

a = ["haha", "hihi", "hoho"]
a.each { |i| i.gsub!("h", "l") }
p a

and even

a = ["2","3", "4"]
a.each { |i| i.replace("#{i} times") }
p a

in fact variables only point to the objects. so you might use them to modify
the object they are currently pointing to. if you got strings, you may
modify them (instead of creating new ones). but unfortunately that won't
work for numbers, since they are no real objects, but - how do we call
them? - first level objects?

--
Ross Bamford - rosco@roscopeco.REMOVE.co.uk