LINUX.ORG.RU

Обьясните поведение метода «sub!» в Ruby

 ,


1

2

$(сабж) в следующем куске кода

irb(main):115:0> a = {:t1 => 'sa ma ra', :t2 => 'John'}
=> {:t1=>"sa ma ra", :t2=>"John"}
irb(main):116:0> b = a.clone
=> {:t1=>"sa ma ra", :t2=>"John"}
irb(main):117:0> b
=> {:t1=>"sa ma ra", :t2=>"John"}
irb(main):118:0> b[:t2] = 'Jack'
=> "Jack"
irb(main):119:0> a
=> {:t1=>"sa ma ra", :t2=>"John"}
irb(main):120:0> b
=> {:t1=>"sa ma ra", :t2=>"Jack"}
irb(main):121:0> b[:t1].sub!('ma', 'ha')
=> "sa ha ra"
irb(main):122:0> b
=> {:t1=>"sa ha ra", :t2=>"Jack"}
irb(main):123:0> a
=> {:t1=>"sa ha ra", :t2=>"John"}
irb(main):124:0> 
★★★★★

Все объекты хранятся по ссылкам. clone делает копию объекта, но копия указывает на те же самые строки. Когда ты присваиваешь ключу новую строку в хэше, всё ок. Но когда ты вызываешь метод, который изменяет состояние строки, то меняется та общая строка, на которую указывают оба хэша. Всё очевидно же.

Что делать? Это: Marshal.load(Marshsl.dump(array))

geekless ★★
()
Последнее исправление: geekless (всего исправлений: 1)
Ответ на: комментарий от marvin_yorke

тоесть по факту пока я не начал изменять объект *целиком* — ссылка установлена на тот же объект?

ZuBB ★★★★★
() автор топика
Ответ на: комментарий от ZuBB

и после того, как начал, как видишь, тоже.
Т.е. в объекте у тебя условно ряд полей, содержащих ссылки. Shallow copy копирует поля, но не данные, на которые они ссылаются. Тебе нужен deep copy, как оно в руби делается, я не знаю

marvin_yorke ★★★
()
Ответ на: комментарий от ZuBB

Нет. Ты склонировал таблицу (hash) ссылок на строки. Теперь у тебя две независимые таблицы ссылок, но указатели на строки одинаковые и строки в одном экземпляре. sub! изменил строку (без клонирования)

anonymous
()
Ответ на: комментарий от ZuBB

пока я не начал изменять объект *целиком*

Неправильно мыслишь, отсюда и неочевидность такой ошибки. Надо мыслить так: «Пока я не изменил значение в хэше так, чтобы оно указывало на другой объект.» Приучи себя думать в рамках ссылок на объекты, а не самих объектов, тогда такие места в коде научишься интуитивно чувствовать.

geekless ★★
()
Последнее исправление: geekless (всего исправлений: 1)
Ответ на: комментарий от ZuBB

хотя конкретно в твоем случае лучше
b[:t1] = b[:t1].sub('ma', 'ha')
sub возвращает новую строку, в отличие от sub! который модифицирует текущую

marvin_yorke ★★★
()
Ответ на: комментарий от geekless

Слушай этого товарища. Руби не делает глубокое копирование при ".clone".

anonymous
()

всем спасибо за обьяснения

ZuBB ★★★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.