Ruby две пременные изменяются вместе

программирование ruby

В методе одного класса выполняется:
new_state=state.add_line(action,1)
bfs_queue[new_state.cost]<<new_state
new_state2=state.add_line(action,2) #здесь вместе с new_state изменяется new_state2. Почему и как этого избежать?
bfs_queue[new_state2.cost]<<new_stat

Метод класса, к которому принадлежат state, new_state, new_state2:
def add_line(action,number_of_circuits)
q=self.dup
l=Power_line.new(action,number_of_circuits)
l.line.each{|i| q.consumers_frontier<<q.consumers_list[i] if !(q.consumers_frontier.include?(q.consumers_list[i]))}
q.lines_list<<l
q.cost+=l.cost
q
end

Примечание:
Прямо скажем, я неопытный программист.
Вот проект как он есть http://dl.dropbox.com/u/40400409/Project/Project.zip
Сейчас сяду приводить в удобоваримый вид

Примечание:
ruby-debagger'ом я и определил что они меняются вместе.
А конкретно вот в этом кусочке кода:

def add_line(action,number_of_circuits)
q=self.clone
l=Power_line.new(action,number_of_circuits)
l.line.each{|i| q.consumers_frontier<<q.consumers_list[i] if !(q.consumers_frontier.include?(q.consumers_list[i]))} #внимание
q.lines_list<<l
q.cost+=l.cost

q
end

все изменения q дублируюются в self и при использовании dup и clone.
Или ни один из них не подходит для создания независимого объекта?
Вот из документации:
class Klass
attr_accessor :str
end
s1 = Klass.new #=> #<Klass:0x401b3a38>
s1.str = "Hello" #=> "Hello"
s2 = s1.clone #=> #<Klass:0x401b3998 @str="Hello">
s2.str[1,4] = "i" #=> "i"
s1.inspect #=> "#<Klass:0x401b3a38 @str=\"Hi\">"
s2.inspect #=> "#<Klass:0x401b3998 @str=\"Hi\">"
То есть clone не подходит.
Для dup подобного примера нет. Но ведет он себя, судя по всему так же.

Примечание:
Вот что нашел по вопросу
http://groups.google.com/group/comp.lang.ruby/browse_frm/thread/8a24226a54e79d24/9667453664f2633d?pli=1
blog.rubybestpractices.com/posts/rklemme/018-Complete_Class.html
http://stackoverflow.com/questions/8691496/instance-variable-still-references-after-dup

То есть я должен определить метод dup и в нем ручками перебить все цать свойств класса? А если они в массивах, то каждый элемент массива отдельно? А при добавлении новых свойств переписывать dup?
Такой хоккей нам не нужен...

Примечание:
А вот и ответ:

class A
attr_accessor :name
def dup
Marshal::load(Marshal.dump(self))
end
end

Вроде работает.
Ответы:
вставьте debugger и покажите состояние
что-то не верится, а повторить я не могу
а вместо "if ! " красивше выглядит "unless" и скобок будет меньше
постарайтесь обозвать переменные вместо l => lines
всесто q => ququmbers чтобы функция переменной вытекала из ее названия
а то так разбираться тяжело
один из постулатов руби: "программа должна быть написана так чтобы ее понимали люди, и только иногда - машины"
и собственно вопрос сформулирован весьма пространно
"здесь вместе с new_state изменяется new_state2. Почему и как этого избежать?"
надо понимать что new_state2 определена к моменту присвоения?
если new_state2 не определа, т.е. nil, то это может означать только что state.add_line(act, 1) == state.add_line(act,2)
в общем пока вопросов больше
puts bfs_queue.inspect


13 лет назад

RPI.su - самая большая русскоязычная база вопросов и ответов. Наш проект был реализован как продолжение популярного сервиса otvety.google.ru, который был закрыт и удален 30 апреля 2015 года. Мы решили воскресить полезный сервис Ответы Гугл, чтобы любой человек смог публично узнать ответ на свой вопрос у интернет сообщества.

Все вопросы, добавленные на сайт ответов Google, мы скопировали и сохранили здесь. Имена старых пользователей также отображены в том виде, в котором они существовали ранее. Только нужно заново пройти регистрацию, чтобы иметь возможность задавать вопросы, или отвечать другим.

Чтобы связаться с нами по любому вопросу О САЙТЕ (реклама, сотрудничество, отзыв о сервисе), пишите на почту [email protected]. Только все общие вопросы размещайте на сайте, на них ответ по почте не предоставляется.