Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Ruby: Общие вопросы > Переменные, непонятное поведение


Автор: MystDeim 17.6.2010, 19:34
Есть такой код:
Код

#1
a = b = 'aaa'
puts b.inspect
a[0] = 'b'
puts b.inspect

#1
a = b = 'aaa'
puts a.inspect
b[0] = 'b'
puts a.inspect


И первый и второй блоки выводят:
Код

"aaa"
"baa"

Я знаю что в руби является всё объектами, но получается что в 1 случае b ссылается на a, а во втором наоборт?

Теперь попробуем с числами:
Код

#3
a = b = 100
puts b.inspect
a = 1
puts b.inspect

#4
a = b = 100
puts a.inspect
b = 1
puts a.inspect


И в 3 и в 4 случае всё одинаково:
Код

100
100

Почему так? должно во второй раз должно же быть 1...

Автор: shine 17.6.2010, 20:19
И у чисел и у строк в Ruby есть полезный атрибут object_id. Советую поэкспериментирвать с ним до и во время ваших опытов.

Автор: MystDeim 17.6.2010, 21:03
У чисел object_id всегда оказывается разный, получается ведут себя как обычные скалярные типы.

А у строк object_id одинаковый, еще проверил массивы, тоже самое.

Автор: shine 17.6.2010, 22:55
Вобщем, большинство переменных в руби - ссылки. Когда вы создаете переменные 'a = b = "some text"' вы создаете переменную b и присваиваете ей значение "some text". После этого вы создаете еще одну переменную a и присваиваете ей значение b которое является ссылкой на "some text". В результате вы получаете две ссылки на один объект(object_id) в памяти.
Если вы после этого присвоете a какое-то другое значение эта связь с b пропадет и вы сможете менять переменные независимо друг от друга.
Если вы хотите создать две "истинно независимые" переменные с одинаковыми значениями вы можете использовать метод clone любого объекта:
Код

a = "some text"
b = a.clone # или просто b = "some text"

После этого a и b будут указывать на разные объекты в памяти.

Но создателям языка такая схема показалась слишком простой и они оторвались на целочисленных smile Во-первых есть два типа целочисленных Fixnum и Bignum. Bignum для больших чисел а Fixnum для маленьких. Они взаимно превращаются друг в друга когда значение переменной становится слишком большим (или маленьким).
Но этого оказалось мало. Создатели языка решили прооптимизировать числа и сделали из них Singleton-ы. Каждое число - отдельный объект в памяти и все переменные с одинаковым целочисленным значением ссылаются на один и тот же объект в памяти. Само собой для этих Singleton-ов не работает метод clone по самой природе этих переменных.

Вот такие дела. Страшно?  smile 

Автор: niksan 18.6.2010, 07:56
hine, очень увлекательно, спасибо ) Расскажите еще чего нить "эдакого", если не сложно ))
Или статейку подобную на хабр наваяйте, думаю, все почитают с удовольствием.

Автор: MystDeim 18.6.2010, 12:22
shine, Хотел сделать еще один эксперимент, но прочитал ваш пост еще раз внимательно и всё встало на места smile  Спасибо!

Посоветуйте почитать чего-нибуль про такие тонкости, 
Цитата

Каждое число - отдельный объект в памяти и все переменные с одинаковым целочисленным значением ссылаются на один и тот же объект в памяти. 
 - вот это я не знал, отсюда и путаница возникла.

P.S.
Цитата

Вот такие дела. Страшно? 

Да... с руби шутки плохи!  smile 

Автор: shine 18.6.2010, 13:16
Цитата(MystDeim @ 18.6.2010,  12:22)
Посоветуйте почитать чего-нибуль про такие тонкости

Посоветовать что-то сложно т.к. в рунете толковых материалов по руби нет. Если нет проблем с английским и есть возможность немного заплатить то могу посоветовать http://www.pragprog.com/screencasts/v-dtrubyom/the-ruby-object-model-and-metaprogramming. Там он рассказывает о внутреннем строении классов, модулей в руби, о наследовании и метапрограммировании. Вобщем весьма полезная информация.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)