+= vs << when appending arrays to an array

D

Doug Beaver

hello,

i'm looking for a nice idiomatic way to append to an array. i'm porting
some encryption code from C to ruby, i don't have the code in front of
me but a relevant example is below:

def translate(str="")
ret = []
str.each_byte { |byte| ret << byte }
ret
end

bytes = []
bytes << translate("foo")
bytes += translate("foo")

p bytes

i'm using ruby 1.6.8, btw...

elsewhere in my code, i'm using << to append bytes onto the bytes array,
but for the functions that return arrays of bytes, i have to use += to
make sure the flattened values get added to the target array. if i use
<<, it appends the array returned from the function back onto the target
array. i'd like to use << everywhere as it makes the code more readable
(imo), so is there some syntax i can throw in front of the translate()
call to make the << do the right thing?

i've considered both overloading Array.<< or making my own subclass and
making a smarter <<. i realize that << can't tell if your intent is to
append the array itself ([1,2,3]) or its values (1,2,3). i guess my
real question is, can i get the desired behavior without making a
subclass or redefining <<? i hope my question is clear...

thanks,

doug
 
R

Robert Klemme

Doug Beaver said:
hello,

i'm looking for a nice idiomatic way to append to an array. i'm porting
some encryption code from C to ruby, i don't have the code in front of
me but a relevant example is below:

def translate(str="")
ret = []
str.each_byte { |byte| ret << byte }
ret
end

bytes = []
bytes << translate("foo")
bytes += translate("foo")

p bytes

i'm using ruby 1.6.8, btw...

elsewhere in my code, i'm using << to append bytes onto the bytes array,
but for the functions that return arrays of bytes, i have to use += to
make sure the flattened values get added to the target array. if i use
<<, it appends the array returned from the function back onto the target
array. i'd like to use << everywhere as it makes the code more readable
(imo), so is there some syntax i can throw in front of the translate()
call to make the << do the right thing?

You should use "push" with "*" over "+=" since it is more efficient. "+="
creates a new instance before reassigning to that:

"+=":
irb(main):001:0> a=%w{a b c}
["a", "b", "c"]
irb(main):002:0> b=[1,2,3]
[1, 2, 3]
irb(main):003:0> a.__id__
22401168
irb(main):004:0> a += b
["a", "b", "c", 1, 2, 3]
irb(main):005:0> a.__id__
22388400
irb(main):006:0>

"push":
irb(main):011:0> a=%w{a b c}
["a", "b", "c"]
irb(main):012:0> b=[1,2,3]
[1, 2, 3]
irb(main):013:0> a.__id__
22192460
irb(main):014:0> a.push *b
["a", "b", "c", 1, 2, 3]
irb(main):015:0> a.__id__
22192460
irb(main):016:0>
i've considered both overloading Array.<< or making my own subclass and
making a smarter <<. i realize that << can't tell if your intent is to
append the array itself ([1,2,3]) or its values (1,2,3). i guess my
real question is, can i get the desired behavior without making a
subclass or redefining <<? i hope my question is clear...

You can do it via push, but you can't with your own implementation of <<
since you would want to do

a << *translate("foo")

which isn't possible to do because it yields a syntax error.

Otherwise you would have to add the logic you mentioned and do a "push *"
for all Enumerables. This way you can never append an array as such with
this operator other than doing:

a << [[1,2,3]]

which is a bit odd because of the nesting.

Regards

robert
 

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

No members online now.

Forum statistics

Threads
473,996
Messages
2,570,238
Members
46,826
Latest member
robinsontor

Latest Threads

Top