How does Array's each method change its elements ?

W

w wg

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.
 
S

Sebastian Hungerecker

w said:
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
 
P

Peña, Botp

From: w wg [mailto:[email protected]]=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
=3D> ["how", "are", "you"]
c =3D a.map{ |x| x + "-" }
=3D> ["how-", "are-", "you-"]
=3D> ["how", "are", "you"]
=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]
=3D> [1, 2, 3]
=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]
=3D> [1, 2, 3]
=3D> [2, 3, 4]

hth
kind regards -botp
 
W

w wg

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 said:
From: w wg [mailto:[email protected]]
#..
# 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
=3D> ["how", "are", "you"]
c =3D a.map{ |x| x + "-" }
=3D> ["how-", "are-", "you-"]
=3D> ["how", "are", "you"]
=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]
=3D> [1, 2, 3]
=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]
=3D> [1, 2, 3]
=3D> [2, 3, 4]

hth
kind regards -botp



--=20
 
S

Sebastian Hungerecker

w said:
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
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
 
S

Sebastian Hungerecker

Rados=B3aw Bu=B3at said:
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: (e-mail address removed)
ICQ: 205544826
 
R

Rick DeNatale

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

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,534
Members
45,007
Latest member
obedient dusk

Latest Threads

Top