Непонимание назначения переменной (массива) в Ruby (с методом push) - PullRequest
2 голосов
/ 09 сентября 2010

Я обнаружил недостаток в моем понимании Ruby или теории программирования или того и другого.Посмотрите на этот код:

#!/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

Вывод этого:

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

Вопрос A: Как push на local_ar_2 изменяет два других массива?Насколько я понимаю, локальные переменные заключались в том, что после их создания они не должны влиять на другие переменные, поскольку они локальные.

Вопрос B: Как можно избежать подобных вещей?Исходя из Си и Перла, это просто поражает.

Ответы [ 2 ]

9 голосов
/ 09 сентября 2010

Ruby работает со ссылками!Запомни.Если вам нужна копия, вы должны сделать это следующим образом:

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

Редактировать:

Примеры:

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

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

но:

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: => "привет"

но:

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"

Вы можете прочитать все об этом здесь:http://ruby -doc.org / Docs / ProgrammingRuby / .Прокрутите вниз до «Переменные» почти внизу страницы.

3 голосов
/ 09 сентября 2010

В Ruby вы не «создаете переменные», вы создаете объекты (в вашем случае массив) и присваиваете их переменным.Итак, в вашем примере у вас есть один массив с двумя именами local_ar и local_ar_2.После этого вы изменяете объект, а не переменные (они все еще указывают на один и тот же измененный объект).

Вы говорите, что вы пришли из C, взгляните на этот пример:

int a[5];
int * b;

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

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

Какой номер будет напечатан?Это почти то же самое, что происходит в коде Ruby.

Одно замечание: использование for для перебора массива не является идиоматическим в Ruby.Обычно используется:

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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...