Loser question

Ok. I’m a loser. I’ve been told and warned. But I still got bit.

If I do:

irb(main):001:0> GOLF = [ 1, 2, 3]
=> [1, 2, 3]
irb(main):002:0> g = GOLF
=> [1, 2, 3]
irb(main):003:0> g << 4
=> [1, 2, 3, 4]
irb(main):004:0> g
=> [1, 2, 3, 4]
irb(main):005:0> h = GOLF
=> [1, 2, 3, 4]

Notice that h is [ 1, 2, 3, 4 ] and GOLF has changed its value.

I understand why. Thats not my question.

My question is what or how do most ruby people do this?

Do you simply do this:

irb(main):001:0> GOLF = [ 1, 2, 3 ]
=> [1, 2, 3]
irb(main):002:0> g = GOLF.dup
=> [1, 2, 3]
irb(main):003:0> g << 4
=> [1, 2, 3, 4]
irb(main):004:0> h = GOLF
=> [1, 2, 3]

Or, do you usually hide GOLF inside a method – which does the dup. How
is this handled most of the time?

Thank you very much,
pedz

On 10/25/07, Perry S. [email protected] wrote:

Ok. I’m a loser. I’ve been told and warned. But I still got bit.

Man, you’re too hard on yourself!

=> [1, 2, 3, 4]

is this handled most of the time?
If you want GOLF to be immutable, you can freeze it:

$ irb --simple-prompt

GOLF = [ 1, 2, 3 ]
=> [1, 2, 3]
GOLF.freeze
=> [1, 2, 3]
h = GOLF
=> [1, 2, 3]
h << 4
TypeError: can’t modify frozen array
from (irb):4:in `<<’
from (irb):4
from :0

I would say that it depends on the context. If this is something you
will do often, make a function out of it to keep things DRY, but if it’s
just once or twice , do it inline. Since we are not talking about a
large number of lines of code and the intent is fairly obvious, it
really doesn’t matter too much.

my $.02
-Bill

Michael G. wrote:

–Michael


Sincerely,

William P.

I have a lot of functions that do things like this:

I have a function that takes an array, and sets various additional
"default’ values in it. I first clone what is passed in:

newvals = args.clone

and then modify newvals.

I assume .dup and .clone are about the same?

–Michael

On 10/25/07, Perry S. [email protected] wrote:

=> [1, 2, 3, 4]
irb(main):004:0> g
=> [1, 2, 3, 4]
irb(main):005:0> h = GOLF
=> [1, 2, 3, 4]

Notice that h is [ 1, 2, 3, 4 ] and GOLF has changed its value.

Not really, GOLF still points to the same array.

The array is mutable though, and you may want to freeze it as others
have pointed out.

Sincerely,
Isak

I’m not quite sure what you’re driving at here. Were you expecting
different behavior than what you showed in your original post? I mean,
if h and g are references to the same object, of course modifying the
object will have a same result no matter which reference you use to
“view” the object.

If your end goal is to create references to two different objects (by
object identity) that begin life with the same contents, then it’s
very common in object oriented programming languages to clone (dup)
the object. Any other behavior than this would be “odd” at best, and
would completely confuse every object oriented programmer out there.

Here is an example of how a language other than Ruby would support
this. The following is a “factory” method used to construct a new
array using the contents of another array written in Objective C:

  • (id)arrayWithArray:(NSArray *)anArray

Here the + indicates that this is a class method returning an array
constructed using a reference to a different array. The array returned
by this method references an new array and does not simply reference
the original array.

Ruby doesn’t actually have this type of factory method, but if you do
this a lot it could be easily added to the Array class. But, is that
really worth it when all you need is:

g = h.dup

I started doing this:

GOLF = [ 1, 2, 3].freeze

Now GOLF can’t change and what it points to can’t change and it is
reasonably compact and somewhat obvious.

irb(main):032:0> S = [ 1, 2, 3, 4 ].freeze
=> [1, 2, 3, 4]
irb(main):033:0> h = S
=> [1, 2, 3, 4]
irb(main):034:0> h << 8
TypeError: can’t modify frozen array
from (irb):34:in `<<’
from (irb):34
from :0
irb(main):035:0> S = 8
(irb):35: warning: already initialized constant S
=> 8