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 does push to local_ar_2 change the two 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 and Perl this is just blowing my mind.

2 Answers 2

9

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.

Sign up to request clarification or add additional context in comments.

Comments

3

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

1 Comment

I like the way you put that first sentence, very concise and informative.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.