[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

How does Array's each method change its elements ?

w wg

9/26/2008 9:05:00 AM

Hi,

I found Array's each method (block) changes its elements sometimes,
but sometimes it don't.

Please look this:

a = [1,2,3,4,5]
b = a.each { |x| x + 1}

puts a
[1,2,3,4,5]
puts b
[1,2,3,4,5]

The array keeps no changed.


But, look another:

a = ["how","are","you"]
b = a.each { |x| x << "-" }
puts a
["how-","are-","you-"]
puts b
["how-","are-","you-"]

The array changed!

I want to know how does Array's each method (block) change its elements ?

Thank you.


--
Wang

6 Answers

Sebastian Hungerecker

9/26/2008 9:21:00 AM

0

w wg wrote:
> I want to know how does Array's each method (block) change its elements ?

It doesn't. You do.

> b = a.each { |x| x + 1}

This executes "x + 1" for every element in the array. Compare the following:
x = 5
x + 1
p x
x is still 5. The expression x+1 does not change the value of x.

> b = a.each { |x| x << "-" }

x = "foo"
x << "-"
p x
Prints "foo-" because << does modify the receiver. I.e. after calling << "-"
the string will contain a "-", so that's what's happening to each element in
the array.

Another note: each returns the receiver, so if you do
b = a.each {...}
b and a will point to the exact same array no matter what happens in the block
(unless you use break inside the block).

HTH,
Sebastian
--
Jabber: sepp2k@jabber.org
ICQ: 205544826

Peña, Botp

9/26/2008 9:56:00 AM

0

From: w wg [mailto:duzuike@gmail.com]=20
#..
# a =3D ["how","are","you"]
# b =3D a.each { |x| x << "-" }
# puts a
# ["how-","are-","you-"]
# puts b
# ["how-","are-","you-"]
#=20
# The array changed!
#=20
# I want to know how does Array's each method (block) change=20
# its elements ?

each just iterates on each element/object of the array. an array is just =
a container of objects (wc includes also arrays). if you use << or =
concat method, you change the object, ergo, you change the array too.

try array#map and just use simple + for concatenation, eg

> a
=3D> ["how", "are", "you"]

> c =3D a.map{ |x| x + "-" }
=3D> ["how-", "are-", "you-"]

> a
=3D> ["how", "are", "you"]

> c
=3D> ["how-", "are-", "you-"]

also note, strings are mutable objects, but, numbers are not.
see,

> a=3D[1,2,3]
=3D> [1, 2, 3]

> b=3Da.each{|x| x+=3D1}
=3D> [1, 2, 3]

> a
=3D> [1, 2, 3]

> b
=3D> [1, 2, 3]

no change
the expression x+=3D1 seems to change the object pointed by var x. but =
no. a new object (eg 2) is now pointed by x, wc is outside of the array. =
ruby cannot change the object 1. for ruby, 1 is always 1. Since we did =
not do anything on the new objects 2,3,4, they just get lost/cleanuped. =
They were there before. You can print them if you're in doubt. But you =
can save them easily if you use array#map.

let's use again map

> b=3Da.map{|x| x+=3D1}
=3D> [2, 3, 4]

> a
=3D> [1, 2, 3]

> b
=3D> [2, 3, 4]

hth
kind regards -botp

w wg

9/27/2008 7:55:00 AM

0

I have noticed that Number elements and String elements of an array
generate diffrent results in its EACH method if you change the
elements. But it is difficult to understand how ruby implements
arrays each method block.

2008/9/26 Pe=F1a, Botp <botp@delmonte-phil.com>:
> From: w wg [mailto:duzuike@gmail.com]
> #..
> # a =3D ["how","are","you"]
> # b =3D a.each { |x| x << "-" }
> # puts a
> # ["how-","are-","you-"]
> # puts b
> # ["how-","are-","you-"]
> #
> # The array changed!
> #
> # I want to know how does Array's each method (block) change
> # its elements ?
>
> each just iterates on each element/object of the array. an array is just =
a container of objects (wc includes also arrays). if you use << or concat m=
ethod, you change the object, ergo, you change the array too.
>
> try array#map and just use simple + for concatenation, eg
>
>> a
> =3D> ["how", "are", "you"]
>
>> c =3D a.map{ |x| x + "-" }
> =3D> ["how-", "are-", "you-"]
>
>> a
> =3D> ["how", "are", "you"]
>
>> c
> =3D> ["how-", "are-", "you-"]
>
> also note, strings are mutable objects, but, numbers are not.
> see,
>
>> a=3D[1,2,3]
> =3D> [1, 2, 3]
>
>> b=3Da.each{|x| x+=3D1}
> =3D> [1, 2, 3]
>
>> a
> =3D> [1, 2, 3]
>
>> b
> =3D> [1, 2, 3]
>
> no change
> the expression x+=3D1 seems to change the object pointed by var x. but no=
a new object (eg 2) is now pointed by x, wc is outside of the array. ruby=
cannot change the object 1. for ruby, 1 is always 1. Since we did not do a=
nything on the new objects 2,3,4, they just get lost/cleanuped. They were t=
here before. You can print them if you're in doubt. But you can save them e=
asily if you use array#map.
>
> let's use again map
>
>> b=3Da.map{|x| x+=3D1}
> =3D> [2, 3, 4]
>
>> a
> =3D> [1, 2, 3]
>
>> b
> =3D> [2, 3, 4]
>
> hth
> kind regards -botp
>
>



--=20
--
WenGe Wang

Sebastian Hungerecker

9/27/2008 8:09:00 AM

0

w wg wrote:
> I have noticed that Number elements and String elements of an array
> generate diffrent results in its EACH method if you change the
> elements.

That's not true. You simply can not change a Numeric object.

> But it is difficult to understand how ruby implements
> arrays each method block.

Array's each method is implemented like this, basically:
class Array
def each()
0.upto(length-1) do |i|
yield self[i]
end
return self
end
end
Except that in reality it's a) not implemented in ruby and b) not using upto.
But if you'd redefine each using the above code there should be no difference
in behaviour except if you also redefine upto.

HTH,
Sebastian
--
Jabber: sepp2k@jabber.org
ICQ: 205544826

Sebastian Hungerecker

9/27/2008 10:15:00 AM

0

Rados=B3aw Bu=B3at wrote:
> There is also "<<" for integers but it works
> different and doesn't change objects because of fact that integers are
> immutable in Ruby.

Well, I would assume that if Integers were mutable, << would still not be a
mutating method as that would really not make much sense.

=2D-=20
Jabber: sepp2k@jabber.org
ICQ: 205544826

Rick DeNatale

9/28/2008 2:02:00 PM

0

MjAwOC85LzI3IFNlYmFzdGlhbiBIdW5nZXJlY2tlciA8c2VwcDJrQGdvb2dsZW1haWwuY29tPjoK
PiBSYWRvc7NhdyBCdbNhdCB3cm90ZToKPj4gVGhlcmUgaXMgYWxzbyAiPDwiIGZvciBpbnRlZ2Vy
cyBidXQgaXQgd29ya3MKPj4gZGlmZmVyZW50IGFuZCBkb2Vzbid0IGNoYW5nZSBvYmplY3RzIGJl
Y2F1c2Ugb2YgZmFjdCB0aGF0IGludGVnZXJzIGFyZQo+PiBpbW11dGFibGUgaW4gUnVieS4KPgo+
IFdlbGwsIEkgd291bGQgYXNzdW1lIHRoYXQgaWYgSW50ZWdlcnMgd2VyZSBtdXRhYmxlLCA8PCB3
b3VsZCBzdGlsbCBub3QgYmUgYQo+IG11dGF0aW5nIG1ldGhvZCBhcyB0aGF0IHdvdWxkIHJlYWxs
eSBub3QgbWFrZSBtdWNoIHNlbnNlLgoKSSB0aGluayB0aGF0IHRoZSBrZXkgaWRlYSBoZXJlIGlz
IHRoYXQgdGhlIGJsb2NrIGFyZ3VtZW50IG9mIGVhY2ggKG9yCmFueSBpdGVyYXRvciBtZXRob2Qg
Zm9yIHRoYXQgbWF0dGVyKSAgY2FuJ3QgYWZmZWN0IGFuIGVsZW1lbnQgb2YgdGhlCmNvbGxlY3Rp
b24gdW5sZXNzIGl0IGludm9rZXMgYSBtdXRhdGluZyBtZXRob2Qgb24gdGhhdCBlbGVtZW50LgoK
VGhlIGZhY3QgdGhhdCBpbW11dGFibGUgb2JqZWN0cyBsaWtlIGludGVnZXJzIGRvbid0IEhBVkUg
YW55IG11dGF0aW5nCm1ldGhvZHMgKGJ5IGRlZmluaXRpb24pIGlzIGEgYml0IG9mIGFuIGFzaWRl
LgoKLS0gClJpY2sgRGVOYXRhbGUKCk15IGJsb2cgb24gUnVieQpodHRwOi8vdGFsa2xpa2VhZHVj
ay5kZW5oYXZlbjIuY29tLwo=