tags:

views:

44

answers:

2

I have discovered a flaw in my understanding of ruby or programming theory or both. Look At This Code:


#!/usr/bin/ruby -w
@instance_ar = [1,2,3,4]
local_ar = @instance_ar
local_ar_2 = local_ar
###
irrelevant_local_ar = [5,6,7,8]
###
for i in irrelevant_local_ar
    local_ar_2.push(i)
end
count = 0
for i in local_ar_2
    puts "local_ar_2 value: #{i} and local_ar value: #{local_ar[count]} and @instance_ar value: #{@instance_ar[count]}\n"
    count += 1
end

The output of that is

local_ar_2 value: 1 and local_ar value: 1 and @instance_ar value: 1
local_ar_2 value: 2 and local_ar value: 2 and @instance_ar value: 2
local_ar_2 value: 3 and local_ar value: 3 and @instance_ar value: 3
local_ar_2 value: 4 and local_ar value: 4 and @instance_ar value: 4
local_ar_2 value: 5 and local_ar value: 5 and @instance_ar value: 5
local_ar_2 value: 6 and local_ar value: 6 and @instance_ar value: 6
local_ar_2 value: 7 and local_ar value: 7 and @instance_ar value: 7
local_ar_2 value: 8 and local_ar value: 8 and @instance_ar value: 8

Question A: How in the world does push to local_ar_2 change 2 other arrays? My understanding of local variables was that once they were created, they should not affect any other variables, being that they were local. Question B: How can I avoid things like this from happening? Coming from C, Perl this is just blowing my mind.

+4  A: 

Hi,

ruby works with references! Keep that in mind. If you want a copy you'd have to do it like:

@instance_ar = [1,2,3,4]
local_ar = @instance_ar.clone
local_ar_2 = local_ar.clone

Edit:

Examples:

a = ["a", "b", "c"]
b = a[0]
b = "d" # we assign a new object to b!

a is: 
=> ["a", "b", "c"] 

but:

a = ["a", "b", "c"]
b = a[0]
b[0] = "d" # we are working with the reference!

a is:
=> ["d", "b", "c"]

a = "hello"
b = a
b += " world" 
# is the same as b = b + " world", we assign a new object!

a is:
=> "hello" 

but:

a = "hello"
b = a
b<<" world"
# we are working with the reference!

a is:
=> "hello world"

a = "abc"
b = a
b[0] = "d" # we are working with the reference

a is:
=> "dbc"

You can read everything about it here: http://ruby-doc.org/docs/ProgrammingRuby/ Scroll down to "Variables" almost at the bottom of the page.

sled
+2  A: 

In Ruby you don't "create variables", you are creating objects (an array, in your case), and assign them to variables. So, in your example, you have a single array with two names, local_ar and local_ar_2. Afterwards you alter the object, not the variables (they both still point to the same altered object).

You say you are coming from C, take a look at this example:

int a[5];
int * b;

a[0] = 10;
a[1] = 20;
b = a;
b[1] = 5;

printf("%d", a[1]);

What number will be printed? It is pretty much the same what's happening in Ruby code.

One note: using for for iterating through an array is not idiomatic in Ruby. One usually uses:

local_ar_2.each_with_index do |i, count|
    puts "local_ar_2 value: #{i} and local_ar value: #{local_ar[count]} and @instance_ar value: #{@instance_ar[count]}\n"
end
Mladen Jablanović