RXL
Технический
Администратор
Offline
Пол:
|
|
« : 05-05-2012 06:24 » |
|
1. Не могу понять, когда и при каких условиях выполняется копирование объекта, а при каких он передается по ссылке. Пример: class Aaa attr_accessor x end
a = Aaa.new x = 1 a.x = x y = a.x x = 2 y = 3 print "#{a.x} #{x} #{y}\n" Результат: "1 2 3". Значит, при передаче аргумента метода и возврата значения создается копия объекта. Возникает резонный вопрос: а можно ли передавать ссылку? Второй тест: class Aaa attr_accessor x end
a = Aaa.new b = Aaa.new b.x = a a.x = 10 b.x.x = 20 print "#{a.x} #{b.x.x}\n" Результат: "20 20". Странно: в документации сказано, что не существует встроенных типов, все типы являются классами и имена являются ссылками на объекты. А на практике получается, что разница есть. Или я где-то ошибся?
|
|
|
Записан
|
... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
|
|
|
RXL
Технический
Администратор
Offline
Пол:
|
|
« Ответ #1 : 05-05-2012 07:05 » |
|
Читал вот это: http://www.opennet.ru/docs/RUS/ruby_guide/Перевод на русский громко заявляет: "Руководство пользователя". Ёпрст! Обзор это! Guide! Зря время потратил.
|
|
|
Записан
|
... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
|
|
|
|
RXL
Технический
Администратор
Offline
Пол:
|
|
« Ответ #3 : 05-05-2012 07:53 » |
|
http://www.chair36.msiu.ru/images/books/roganov-roganova.pdfЕ. А. Роганов, Н. А. Роганова. Программирование на языке Ruby. Учебное пособие Ключевое слово self указывает на объект, вызвавший метод. Запись self.numerator эквивалентна @numerator. Врут! Префиксная форма - прямой доступ к атрибуту, форма от объекта (не забываем, self - текущий объект) реализует доступ через методы внешнего доступа к атрибуту. Слав, это тоже самое, но на английском.
|
|
|
Записан
|
... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
|
|
|
Dimka
Деятель
Команда клуба
Offline
Пол:
|
|
« Ответ #4 : 05-05-2012 14:54 » |
|
RXL, ты как-то очень сложно подходишь к Ruby. Это ж простой язык. И одинаковые вещи там можно делать разными способами - обычно интуитивно понятными. Я вот, честно, ни разу в Ruby не задумывался о копировании ссылок и значений. Ты спросил, я попробовал первое, что в голову пришло, и это работает: a = [1, 2, 3] b = a # reference copy a.pop puts b.join(", ") # 1, 2 a.push 3 c = a.clone # value copy a.pop puts c.join(", ") # 1, 2, 3 P.S. self внутри def-конструкции ко всему прочему описывает статический метод класса.
|
|
« Последнее редактирование: 05-05-2012 14:57 от Dimka »
|
Записан
|
Программировать - значит понимать (К. Нюгард) Невывернутое лучше, чем вправленное (М. Аврелий) Многие готовы скорее умереть, чем подумать (Б. Рассел)
|
|
|
RXL
Технический
Администратор
Offline
Пол:
|
|
« Ответ #5 : 05-05-2012 19:07 » |
|
Дим, в рамках присвоивания переменных друг другу идет присваиванием по ссылке. А вот с методами иначе. Причем клонирование не всегда дает одинаковые результаты (см. мои тесты в начале темы). Я о Ruby задумался как о альтернативе PHP. Я считаю, что PHP - непродуманный язык с большими дырами в поведении, исправление которых не видно даже в плане, и хочу подобрать другой популярный скриптовый язык, где ситуация была бы лучше. Perl, к сожалению, сегодня не популярен. Python мне что-то не приглянулся. Вроде как Ruby популярен. Только я хочу быть уверен в том, что понимаю, что и как работает. В Perl я уверен. В PHP - почти уверен после метода тыка для сложных случаев. Добавлено через 6 минут и 54 секунды:P.S. self внутри def-конструкции ко всему прочему описывает статический метод класса.
Не верю! $ irb irb(main):001:0> class Aaa irb(main):002:1> def initialize irb(main):003:2> @x = 0; irb(main):004:2* end irb(main):005:1> def a(x) irb(main):006:2> @x = x irb(main):007:2> puts self irb(main):008:2> self.b irb(main):009:2> end irb(main):010:1> def b irb(main):011:2> @x += 1 irb(main):012:2> puts self irb(main):013:2> end irb(main):014:1> end => nil irb(main):015:0> a = Aaa.new => #<Aaa:0xb7f8c0e8 @x=0> irb(main):016:0> a.a(10) #<Aaa:0xb7f8c0e8> #<Aaa:0xb7f8c0e8> => nil irb(main):017:0> a => #<Aaa:0xb7f8c0e8 @x=11> irb(main):018:0>
Метод Aaa::b вызван не как статический. На всякий случай, чтобы не говорить о разном. У меня версия 1.8.5. P.S.: про PHP: если у вас сайт на PHP, который выполняется в рамках CGI, то используйте QUERY_STRING=-s для несанкционированного просмотра исходников. Эта дыра есть во версиях за последние пять лет. Видимо для отладки оставляли.
|
|
« Последнее редактирование: 05-05-2012 19:22 от RXL »
|
Записан
|
... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
|
|
|
Dimka
Деятель
Команда клуба
Offline
Пол:
|
|
« Ответ #6 : 05-05-2012 20:12 » |
|
RXL, я твоего кода вообще не понял. В первом примере ты будто бы ожидал, что глобальная переменная x является объектом. Объектом является только значение, а не переменная. И это значение 1. Оно передаётся в x, затем из x в a.x, затем из a.x в y. Чтобы заявленный на пустом месте идентификатор вдруг стал объектом, на который можно ссылаться - это как-то для меня совершенно непонятно. Это ты в каком языке такое видел? Поведение второго примера я уже продемонстрировал: как оно на деле работает. attr_accessor - это вообще макрос, "синтаксический сахар". Кстати, следующие за ним идентификаторы нужно задавать как символьные выражения - через двоеточие. Т.е. attr_accessor :x раскрывается в def x return @x end
def x=(value) @x = value end В данном случае выражение :<expression> будет использовано в макросе так, как оно задано после двоеточия на уровне текста исходного кода. Если ты вместо символьного выражения ставишь глобальную переменную x, результат не всегда будет тот, которого можно было бы ожидать. По поводу self ты меня не понял. class C def self.f # аналогично "def C.f", но избегаем повторять C в разных местах. puts "class" puts self # C - объект RTTI, описание класса, экземпляр метакласса end def g puts "instance" puts self # <C:0x....> - экземпляр класса h self end private def h(object) puts self == object # true end end
C.f c = C.new c.g В теле метода экземпляра self означает ссылку на текущий экземпляр. В теле метода класса self - объект уровня RTTI, описывающий класс - псевдоним идентификатора класса, чтобы упростить рефакторинг. В последнем же качестве в def-конструкции используется для обозначения метода класса (статического метода). P.S. Двойное двоеточие - это раскрытие пространства имён, а не обращение к члену объекта. Класс может рассматриваться как пространство имён, наравне с модулем. Модуль отличается от класса разве что тем, что не может иметь экземпляров, а всё остальное (включая описание статических атрибутов - переменных уровня модуля) допустимо, функции же в модуле по умолчанию "статические", т.е. префикс self писать не нужно.
|
|
« Последнее редактирование: 05-05-2012 20:18 от Dimka »
|
Записан
|
Программировать - значит понимать (К. Нюгард) Невывернутое лучше, чем вправленное (М. Аврелий) Многие готовы скорее умереть, чем подумать (Б. Рассел)
|
|
|
RXL
Технический
Администратор
Offline
Пол:
|
|
« Ответ #7 : 05-05-2012 21:22 » |
|
Разве переменная глобальная? Глобальные переменные имеют префикс "$". У меня локальная переменная внутри модуля "main". Проверка: $ irb irb(main):001:0> def myfunc irb(main):002:1> puts $x irb(main):003:1> end => nil irb(main):004:0> $x = 1 => 1 irb(main):005:0> x = 123 => 123 irb(main):006:0> myfunc 1 => nil
Документация убеждает, что объекты в Ruby динамические, переменные - лишь ссылки на них, присваивание происходит по ссылке. x = 1 y = x Здесь создается объект Fixnum, ссылка на него присваивается "x". Потом та же ссылка присваивается "y". Далее: a.x = x Здесь нет присвоения ссылки - происходит копирование объекта и "@x" присваивается уже ссылка на новый объект. При присваивании более сложного объекта, содержащего в себе ссылки на другие объекты, объект копируется буквально - с сохранением ссылок. Это меня и удивило. Тот же эффект будет при использовании методов с параметрами: параметры в методе ссылаются на копии входных аргументов. Добавлено через 5 минут и 16 секунд:RXL, я твоего кода вообще не понял.
Какого именно? В первом посте или в предыдущем? заявленный на пустом месте идентификатор вдруг стал объектом
О чем речь то? Это ты в каком языке такое видел?
Например, Perl: если я передаю в функцию ссылку или возвращаю ссылку из функции, то никаких скрытых преобразований не происходит. Тоже с присваиванием скалярным переменным ссылок. Добавлено через 6 минут и 23 секунды:Кстати, следующие за ним идентификаторы нужно задавать как символьные выражения - через двоеточие. Т.е. ...
Опечатался с непривычки. Добавь кавычки или двоеточие, но итог примеров из первого поста будет тот же. Про глобальные переменные я уже сказал выше. Тут все переменные без префикса - локальные. Добавлено через 1 минуту и 52 секунды:По поводу self ты меня не понял.
Да, вначале я неправильно понимал. Теперь понял.
|
|
« Последнее редактирование: 05-05-2012 21:57 от RXL »
|
Записан
|
... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
|
|
|
Dimka
Деятель
Команда клуба
Offline
Пол:
|
|
« Ответ #8 : 06-05-2012 05:51 » |
|
Разве переменная глобальная? Глобальные переменные имеют префикс "$". У меня локальная переменная внутри модуля "main". Да. Я просто main по привычке считаю глобальным пространством имён. В том смысле, что x вне функции не будет виден внутри функции (вернее, внутри функции упоминание x будет расценено как собственная локальная переменная) - это правда. Код: (Ruby) a.x = x
Здесь нет присвоения ссылки - происходит копирование объекта и "@x" присваивается уже ссылка на новый объект. Это ещё с чего? a.x начинает содержать ссылку на тот же Fixnum, что и сам x. Т.е. на 1 как константу. class C attr_accessor :x end
def f(y) puts "#{y.object_id}: #{y}" end
x = 1 puts "#{x.object_id}: #{x}" c = C.new c.x = x puts "#{c.x.object_id}: #{c.x}" f x Все три строчки, выводимые на печать, одинаковы, потому что один и тот же объект. Например, Perl: если я передаю в функцию ссылку или возвращаю ссылку из функции, то никаких скрытых преобразований не происходит. Тоже с присваиванием скалярным переменным ссылок. Ты явно что-то путаешь. Может пытаешься думать о ссылке, как об указателе или псевдониме? def f(y) puts y.object_id y = 2 puts y.object_id puts "y = #{y}" end
x = 1 puts x.object_id f x puts "x = #{x}" Здесь создаётся объект Fixnum со значением 1, и в x помещается ссылка на него. Затем происходит вызов функции f, параметр y которой ссылается на тот же Fixnum. Затем внутри функции создаётся новый объект Fixnum со значением 2, и ссылка y переключается на него - теперь указывает на новый объект. Ссылка x, естественно, остаётся неизменной. Т.е. x и y - это две независимые ссылки, а не псевдонимы одной и той же ссылки. И происходит копирование ссылок.
|
|
« Последнее редактирование: 06-05-2012 19:17 от Dimka »
|
Записан
|
Программировать - значит понимать (К. Нюгард) Невывернутое лучше, чем вправленное (М. Аврелий) Многие готовы скорее умереть, чем подумать (Б. Рассел)
|
|
|
RXL
Технический
Администратор
Offline
Пол:
|
|
« Ответ #9 : 06-05-2012 08:35 » |
|
Спасибо, Дим, теперь понятно, в чем моя ошибка. У меня была мысль, как здесь обеспечить косвенность - ссылаться на один и тот же объект в множестве мест. В случае объектов, генерируемых из естественных констант, возникает путаница понимания.
|
|
|
Записан
|
... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
|
|
|
Dimka
Деятель
Команда клуба
Offline
Пол:
|
|
« Ответ #10 : 06-05-2012 09:32 » |
|
RXL, можно, создав указатель - т.е. объект, внутри которого ссылка на нужный объект. class Pointer attr_accessor :value def initialize(value) @value = value end end
def f(ptr) ptr.value = 2 end
ptr = Pointer.new 1 puts "#{ptr.value}" # 1 f ptr puts "#{ptr.value}" # 2
|
|
|
Записан
|
Программировать - значит понимать (К. Нюгард) Невывернутое лучше, чем вправленное (М. Аврелий) Многие готовы скорее умереть, чем подумать (Б. Рассел)
|
|
|
Sla
|
|
« Ответ #11 : 06-05-2012 10:49 » |
|
RXL, можно, создав указатель - т.е. объект, внутри которого ссылка на нужный объект. class Pointer attr_accessor :value def initialize(value) @value = value end end
def f(ptr) ptr.value = 2 end
ptr = Pointer.new 1 puts "#{ptr.value}" # 1 f ptr puts "#{ptr.value}" # 2
Не понял, каким образом получилось 2? Где передалась ссылка на объект
|
|
|
Записан
|
Мы все учились понемногу... Чему-нибудь и как-нибудь.
|
|
|
RXL
Технический
Администратор
Offline
Пол:
|
|
« Ответ #12 : 06-05-2012 10:59 » |
|
Sla, все переменные являются ссылками. Соотв., "f ptr" передает ссылку на ptr в f.
Dimka, а то, что я говорил про ссылки Perl: там переменные рассматриваются как скрытые ссылки на значения, но есть явные ссылки, которые можно присваивать скалярным переменным. Т.е. явная ссылка там выступает значением (двойная косвенность). При присваивании переменных происходит копирование значения.
Добавлено через 4 часа, 42 минуты и 18 секунд: Чем дальше вникаю, тем интереснее. Замечу, синтаксически Ruby совсем не прост. Вариаций очень много и все ситуации надо запомнить, чтобы не путаться.
|
|
« Последнее редактирование: 06-05-2012 18:35 от RXL »
|
Записан
|
... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
|
|
|
Dimka
Деятель
Команда клуба
Offline
Пол:
|
|
« Ответ #13 : 06-05-2012 19:23 » |
|
RXL, в основе Ruby лежит Smalltalk. Концепции объектов и ссылок, а также блоков кода и символьных выражений - всё оттуда. Синтаксис, конечно, другой - более привычный основной массе программистов. Ну и сам подход к кодированию с минимумом "телодвижений" для достижения результата: "короткий разговор". Я бы посоветовал не концентрировать внимание на мелочах, а, напротив, расслабиться и кодировать
|
|
« Последнее редактирование: 06-05-2012 19:25 от Dimka »
|
Записан
|
Программировать - значит понимать (К. Нюгард) Невывернутое лучше, чем вправленное (М. Аврелий) Многие готовы скорее умереть, чем подумать (Б. Рассел)
|
|
|
RXL
Технический
Администратор
Offline
Пол:
|
|
« Ответ #14 : 24-05-2012 18:23 » |
|
Некоторой путаницей, но и удобным решением, является поведение локальных переменных в блоках {}. Передав такой блок в метод можно ссылаться на локальные переменные вызвавшего блока. По сути это замыкания. Такой пример: def func x = 2 yield end
x = 1 func { puts x } Здесь будет распечатано "1". Или более интересный пример: table = [100, 200, 300] puts([0, 2, 1].each {|x| table[x] }.join(', ')) Результат: "100, 300, 200". Назревает вопрос, а нельзя ли использовать замыкания как в Perl, где ими создается эффект статических переменных? { $static_var = 1
sub func { print "$static_var\n"; $static_var++; } } Константы — это немного не то. Они доступны всему классу или модулю, а не одному методу. Добавлено через 9 часов и 20 минут:Управление доступом в Ruby вообще сплошная условность... Не понял назначение фичи "class instance variable". Чем оно обосновывается и какое применение может иметь? Вот пример из книги: class Test @cls_var = 123 def Test.inc @cls_var += 1 end end
Test.inc # -> 124 Test.inc # -> 125 И пример с атрибутом: class Test @cls_var = 123 class <<self attr_reader :cls_var end end
Test.cls_var # -> 123
|
|
« Последнее редактирование: 25-05-2012 03:54 от RXL »
|
Записан
|
... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
|
|
|
Dimka
Деятель
Команда клуба
Offline
Пол:
|
|
« Ответ #15 : 25-05-2012 07:43 » |
|
Назревает вопрос, а нельзя ли использовать замыкания как в Perl, где ими создается эффект статических переменных? Есть же статические переменные с префиксом $ для функций в рамках модуля или класса. Ты сам их поминал выше. Причём тут блоки? class C $x = 1 def self.f puts $x end end
C.f Ну здесь ты вместо { ... } написал class ... end. А в чём ещё разница? Я лично предпочитаю вместо фигурных скобок писать длиннее do ... end - то же самое, но мне кажется более эстетичным для длинных многострочных блоков. И вместо each использовать цикл for ... in ... (т.е. foreach) - опять же по эстетическим соображениям. class C def each 10.times do | x | yield x, x ** 2 end end end
o = C.new for x, x2 in o puts "#{x} #{x2}" end Не понял назначение фичи "class instance variable". Чем оно обосновывается и какое применение может иметь? Дословно это из Smalltalk. Обычный атрибут объекта (нестатическое поле), префикс @. Всегда private. Область видимости - объект (а не метод). Префикс $ описывает атрибут класса (статическое поле). Тоже private. Область видимости - класс. Она же - локальная переменная модуля с областью видимости в пределах модуля. Назначение атрибутов объекта... Я думаю, это вопрос философский Однако все пользуются.
|
|
|
Записан
|
Программировать - значит понимать (К. Нюгард) Невывернутое лучше, чем вправленное (М. Аврелий) Многие готовы скорее умереть, чем подумать (Б. Рассел)
|
|
|
RXL
Технический
Администратор
Offline
Пол:
|
|
« Ответ #16 : 25-05-2012 08:00 » |
|
С префиксом $ - это глобальные переменные. В рамках класса/модуля - с префиксом @@. Замыкание же делается для локальных переменных. Ну здесь ты вместо { ... } написал class ... end. А в чём ещё разница? Кардинальная разница. Блок в Perl не является ни классом, ни модулем (что в Perl одно и тоже). И в нем можно определять локальные переменные. Не использовать общие локальные переменные метода или класса/модуля, а иметь свои. Объясню поведение Perl в вышеприведенном примере. Блок {} объявлен в глобальном пространстве какого-либо модуля. Когда подгружается код модуля, происходит выполнение глобальных выражений и проверка функций. Внутри блока создается локальная переменная, которая используется в функции, определенной в этом же блоке и по этому при выходе из блока переменная не уничтожается, а создается замыкание, что сродни статической переменной. В модуле больше никому данная переменная не видна - только функциям внутри этого блока. В общем, картина мира правила видимости переменных и управление доступом к ним в этих языках кардинально отличаются. Добавлено через 12 минут и 34 секунды:Не понял назначение фичи "class instance variable". Чем оно обосновывается и какое применение может иметь? Дословно это из Smalltalk. Обычный атрибут объекта (нестатическое поле), префикс @. Всегда private. Область видимости - объект (а не метод). Префикс $ описывает атрибут класса (статическое поле). Тоже private. Область видимости - класс. Она же - локальная переменная модуля с областью видимости в пределах модуля. Назначение атрибутов объекта... Я думаю, это вопрос философский Однако все пользуются. Нет-нет-нет. Дим, речь не о переменных объекта и атрибутах (суть есть переменная объекта + методы доступа). Там переменные именно класса, но класс рассматривается как объект. class X @var = 100
def self.var @var end
def initialize @var = 200 end
def var @var end end X.var # -> 100 X.new.var # -> 200 X.var # -> 100 X.new.var # -> 200 X.var # -> 100 Это разные переменные! Повторю префиксы, чтобы нам не путаться: 1. $ - видимость уровня приложения. 2. @@ - видимость уровня класса или модуля. 3. @ - видимость уровня объекта 4. Без префикса - локальная видимость.
|
|
« Последнее редактирование: 25-05-2012 08:22 от RXL »
|
Записан
|
... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
|
|
|
Dimka
Деятель
Команда клуба
Offline
Пол:
|
|
« Ответ #17 : 25-05-2012 08:54 » |
|
В рамках класса/модуля - с префиксом @@. Замыкание же делается для локальных переменных. Правильно. Но в твоём Perl-коде описана функция и вне её - переменная, статическая для функции, и с ограниченной областью видимости. В моём примере сделано в точности то же самое. Без функции нет разговора о замыкании локальных переменных. Функции же в Ruby вне себя видят лишь переменные с префиксами @, @@, $, но не видят переменных без префиксов. О чём тогда вопрос? Кардинальная разница. Блок в Perl не является ни классом, ни модулем (что в Perl одно и тоже). И в нем можно определять локальные переменные. Не использовать общие локальные переменные метода или класса/модуля, а иметь свои. Тут, как говорится: "Вам шашечки или ехать?" Т.е. тебе слово class не нравится в качестве блока для хранения переменных и функций? Или же ты хочешь, чтобы внутри блоков Ruby можно было бы определять функции? Т.е. чтобы шли инструкции исполняемого кода, потом бац - функция, потом опять исполняемый код? А зачем? Для этого как раз и существуют блоки. Блоки анонимны (т.е. ведут себя как лямбда-функции), но поскольку они являются объектами, их можно хранить в переменных (т.е. именовать) и использовать как функции. def f(b) b.call end
puts "Begin" x = 1 b = proc do puts "#{x}" end b.call # 1 x = 2 b.call # 2 x = 3 f b # 3 puts "End" Контекст блока привязан к нему, даже если сам блок вызывается в каком-то другом месте (в другой функции). Вообще "конструирование" модуля или какого-то блока, являющегося замыканием есть ни что иное как конструирование объекта, но это имеет смысл в нетипизированных языках, где нет классов. В том же JavaScript так. Если есть классы, зачем такие "конструирования"? Если нужны динамические создаваемые классы - есть eval, есть примеси. Объясню поведение Perl в вышеприведенном примере. Блок {} объявлен в глобальном пространстве какого-либо модуля. Когда подгружается код модуля, происходит выполнение глобальных выражений и проверка функций. Внутри блока создается локальная переменная, которая используется в функции, определенной в этом же блоке и по этому при выходе из блока переменная не уничтожается, а создается замыкание, что сродни статической переменной. В модуле больше никому данная переменная не видна - только функциям внутри этого блока. По внешним признакам ты описал объект-синглетон. Ему соответствует класс или модуль Ruby со статическими переменными и статическими функциями. (Модуль в отличие от класса может иметь примеси других модулей.) Там переменные именно класса, но класс рассматривается как объект. Не знаю, где "там", но в Ruby всё является объектами - и модули, и классы, и блоки кода. А что не так?
|
|
|
Записан
|
Программировать - значит понимать (К. Нюгард) Невывернутое лучше, чем вправленное (М. Аврелий) Многие готовы скорее умереть, чем подумать (Б. Рассел)
|
|
|
RXL
Технический
Администратор
Offline
Пол:
|
|
« Ответ #18 : 25-05-2012 09:50 » |
|
Вопрос не шашечек. Просто примеряю Ruby на привычную картину мира, где есть статические переменные. Не знаю, где "там", но в Ruby всё является объектами - и модули, и классы, и блоки кода. А что не так? Хочу понять, зачем это нужно. Побочный эффект или намеренное решение? Я именно о "class instance variable".
|
|
« Последнее редактирование: 25-05-2012 10:04 от RXL »
|
Записан
|
... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
|
|
|
Dimka
Деятель
Команда клуба
Offline
Пол:
|
|
« Ответ #19 : 25-05-2012 11:45 » |
|
Хочу понять, зачем это нужно. Побочный эффект или намеренное решение? Я именно о "class instance variable". Не понимаю, о чём спрашиваешь. Зачем "зоопарк" из разных способов замыканий? Чтобы всем понравиться: в Ruby каждый пишет, как ему удобнее. Если народ привык к переменным экземпляра, то почему бы им не быть в языке?
|
|
|
Записан
|
Программировать - значит понимать (К. Нюгард) Невывернутое лучше, чем вправленное (М. Аврелий) Многие готовы скорее умереть, чем подумать (Б. Рассел)
|
|
|
Sla
|
|
« Ответ #20 : 25-05-2012 11:49 » |
|
> в Ruby каждый пишет, как ему удобнее.
Бред
|
|
|
Записан
|
Мы все учились понемногу... Чему-нибудь и как-нибудь.
|
|
|
Dimka
Деятель
Команда клуба
Offline
Пол:
|
|
« Ответ #21 : 25-05-2012 11:56 » |
|
Sla, ты пишешь, как тебе удобнее. Только зачем это навязывать остальным? Вон, Рома хочет, чтобы как в Perl было - вот и договариваемся о "типографских соглашениях" Как та же фигня в другом синтаксисе выглядит.
|
|
|
Записан
|
Программировать - значит понимать (К. Нюгард) Невывернутое лучше, чем вправленное (М. Аврелий) Многие готовы скорее умереть, чем подумать (Б. Рассел)
|
|
|
Sla
|
|
« Ответ #22 : 25-05-2012 12:00 » |
|
Но ведь кто-то это должен потом читать.
|
|
|
Записан
|
Мы все учились понемногу... Чему-нибудь и как-нибудь.
|
|
|
Dimka
Деятель
Команда клуба
Offline
Пол:
|
|
« Ответ #23 : 25-05-2012 12:18 » |
|
Sla, imho, если человек умеет читать Perl, он прочитает что угодно Вот, к примеру, стиль бесклассового ООП в духе JavaScript на Ruby. Нечто похожее как раз и есть в Perl. def like_js_constructor my_private_local_variable = 1 my_method_implementation = proc do puts "#{my_private_local_variable}" my_private_local_variable += 1 end return { :my_method => my_method_implementation } end
like_js_object_1 = like_js_constructor like_js_object_2 = like_js_constructor like_js_object_1[:my_method].call # 1 like_js_object_1[:my_method].call # 2 like_js_object_2[:my_method].call # 1 Функция-конструктор при каждом вызове создаёт хэш, содержащий какие-то публичные объекты - будь то данные или функции, обычно функции. Эти функции-методы есть блоки, созданные в едином замыкании и работающие с общими локальными переменными конструктора, каковые выступают в качестве приватных атрибутов объекта. Для каждого вызова конструктора возникает отдельный экземпляр замыкания, который и есть по сути объект, а хэш для него - интерфейс. В памяти хранятся 2 "физических" объекта: замыкание (с неявными ссылками на него) и хэш (с явными ссылками на него). Замыкание существует, пока существует хэш с блоками, ссылающимися на замыкание.
|
|
« Последнее редактирование: 25-05-2012 12:27 от Dimka »
|
Записан
|
Программировать - значит понимать (К. Нюгард) Невывернутое лучше, чем вправленное (М. Аврелий) Многие готовы скорее умереть, чем подумать (Б. Рассел)
|
|
|
|