Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: Пытаюсь изучить Ruby. Возникают вопросы.  (Прочитано 21840 раз)
0 Пользователей и 1 Гость смотрят эту тему.
RXL
Технический
Администратор

Offline Offline
Пол: Мужской

WWW
« : 05-05-2012 06:24 » 

1. Не могу понять, когда и при каких условиях выполняется копирование объекта, а при каких он передается по ссылке.

Пример:
Код: (Ruby)
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". Значит, при передаче аргумента метода и возврата значения создается копия объекта. Возникает резонный вопрос: а можно ли передавать ссылку?

Второй тест:
Код: (Ruby)
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 Offline
Пол: Мужской

WWW
« Ответ #1 : 05-05-2012 07:05 » 

Читал вот это: http://www.opennet.ru/docs/RUS/ruby_guide/
Перевод на русский громко заявляет: "Руководство пользователя". Ёпрст! Обзор это! Guide! Зря время потратил.
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Sla
Команда клуба

ua
Offline Offline
Пол: Мужской

WWW
« Ответ #2 : 05-05-2012 07:13 » 

Читал вот это: http://www.opennet.ru/docs/RUS/ruby_guide/
Перевод на русский громко заявляет: "Руководство пользователя". Ёпрст! Обзор это! Guide! Зря время потратил.
Улыбаюсь
После твоего вопроса, тоже наткнулся на это руководство пользователя.

Но мне больше понравилось вот это http://www.rubyist.net/~slagell/ruby/accessors.html
Записан

Мы все учились понемногу... Чему-нибудь и как-нибудь.
RXL
Технический
Администратор

Offline Offline
Пол: Мужской

WWW
« Ответ #3 : 05-05-2012 07:53 » 

http://www.chair36.msiu.ru/images/books/roganov-roganova.pdf
Е. А. Роганов, Н. А. Роганова. Программирование на языке Ruby. Учебное пособие

Цитата
Ключевое слово self указывает на объект, вызвавший метод. Запись
self.numerator эквивалентна @numerator.

Врут! Префиксная форма - прямой доступ к атрибуту, форма от объекта (не забываем, self - текущий объект) реализует доступ через методы внешнего доступа к атрибуту.


Слав, это тоже самое, но на английском.
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #4 : 05-05-2012 14:54 » 

RXL, ты как-то очень сложно подходишь к Ruby. Это ж простой язык. И одинаковые вещи там можно делать разными способами - обычно интуитивно понятными.

Я вот, честно, ни разу в 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 Offline
Пол: Мужской

WWW
« Ответ #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
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #6 : 05-05-2012 20:12 » 

RXL, я твоего кода вообще не понял.

В первом примере ты будто бы ожидал, что глобальная переменная x является объектом. Объектом является только значение, а не переменная. И это значение 1. Оно передаётся в x, затем из x в a.x, затем из a.x в y. Чтобы заявленный на пустом месте идентификатор вдруг стал объектом, на который можно ссылаться - это как-то для меня совершенно непонятно. Это ты в каком языке такое видел?

Поведение второго примера я уже продемонстрировал: как оно на деле работает. attr_accessor - это вообще макрос, "синтаксический сахар". Кстати, следующие за ним идентификаторы нужно задавать как символьные выражения - через двоеточие. Т.е.
Код: (Ruby)
attr_accessor :x
раскрывается в
Код: (Ruby)
def x
  return @x
end

def x=(value)
  @x = value
end
В данном случае выражение :<expression> будет использовано в макросе так, как оно задано после двоеточия на уровне текста исходного кода. Если ты вместо символьного выражения ставишь глобальную переменную x, результат не всегда будет тот, которого можно было бы ожидать.

По поводу self ты меня не понял.
Код: (Ruby)
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 Offline
Пол: Мужской

WWW
« Ответ #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 динамические, переменные - лишь ссылки на них, присваивание происходит по ссылке.

Код: (Ruby)
x = 1
y = x

Здесь создается объект Fixnum, ссылка на него присваивается "x". Потом та же ссылка присваивается "y".
Далее:

Код: (Ruby)
a.x = x

Здесь нет присвоения ссылки - происходит копирование объекта и "@x" присваивается уже ссылка на новый объект.
При присваивании более сложного объекта, содержащего в себе ссылки на другие объекты, объект копируется буквально - с сохранением ссылок. Это меня и удивило.
Тот же эффект будет при использовании методов с параметрами: параметры в методе ссылаются на копии входных аргументов.


Добавлено через 5 минут и 16 секунд:
RXL, я твоего кода вообще не понял.

Какого именно? В первом посте или в предыдущем?

заявленный на пустом месте идентификатор вдруг стал объектом

О чем речь то?

Это ты в каком языке такое видел?

Например, Perl: если я передаю в функцию ссылку или возвращаю ссылку из функции, то никаких скрытых преобразований не происходит. Тоже с присваиванием скалярным переменным ссылок.


Добавлено через 6 минут и 23 секунды:
Кстати, следующие за ним идентификаторы нужно задавать как символьные выражения - через двоеточие. Т.е. ...

Опечатался с непривычки. Добавь кавычки или двоеточие, но итог примеров из первого поста будет тот же.
Про глобальные переменные я уже сказал выше. Тут все переменные без префикса - локальные.

Добавлено через 1 минуту и 52 секунды:
По поводу self ты меня не понял.

Да, вначале я неправильно понимал. Теперь понял.
« Последнее редактирование: 05-05-2012 21:57 от RXL » Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #8 : 06-05-2012 05:51 » 

Цитата: RXL
Разве переменная глобальная? Глобальные переменные имеют префикс "$". У меня локальная переменная внутри модуля "main".
Да. Я просто main по привычке считаю глобальным пространством имён. В том смысле, что x вне функции не будет виден внутри функции (вернее, внутри функции упоминание x будет расценено как собственная локальная переменная) - это правда.

Цитата: RXL
Код: (Ruby)
a.x = x

Здесь нет присвоения ссылки - происходит копирование объекта и "@x" присваивается уже ссылка на новый объект.
Это ещё с чего? a.x начинает содержать ссылку на тот же Fixnum, что и сам x. Т.е. на 1 как константу.
Код: (Ruby)
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
Все три строчки, выводимые на печать, одинаковы, потому что один и тот же объект.

Цитата: RXL
Например, Perl: если я передаю в функцию ссылку или возвращаю ссылку из функции, то никаких скрытых преобразований не происходит. Тоже с присваиванием скалярным переменным ссылок.
Ты явно что-то путаешь. Может пытаешься думать о ссылке, как об указателе или псевдониме?

Код: (Ruby)
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 Offline
Пол: Мужской

WWW
« Ответ #9 : 06-05-2012 08:35 » 

Спасибо, Дим, теперь понятно, в чем моя ошибка.
У меня была мысль, как здесь обеспечить косвенность - ссылаться на один и тот же объект в множестве мест. В случае объектов, генерируемых из естественных констант, возникает путаница понимания.


Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #10 : 06-05-2012 09:32 » 

RXL, можно, создав указатель - т.е. объект, внутри которого ссылка на нужный объект.

Код: (Ruby)

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
Команда клуба

ua
Offline Offline
Пол: Мужской

WWW
« Ответ #11 : 06-05-2012 10:49 » 

RXL, можно, создав указатель - т.е. объект, внутри которого ссылка на нужный объект.

Код: (Ruby)

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 Offline
Пол: Мужской

WWW
« Ответ #12 : 06-05-2012 10:59 » 

Sla, все переменные являются ссылками. Соотв., "f ptr" передает ссылку на ptr в f.

Dimka, а то, что я говорил про ссылки Perl: там переменные рассматриваются как скрытые ссылки на значения, но есть явные ссылки, которые можно присваивать скалярным переменным. Т.е. явная ссылка там выступает значением (двойная косвенность). При присваивании переменных происходит копирование значения.


Добавлено через 4 часа, 42 минуты и 18 секунд:
Чем дальше вникаю, тем интереснее. Замечу, синтаксически Ruby совсем не прост. Вариаций очень много и все ситуации надо запомнить, чтобы не путаться.
« Последнее редактирование: 06-05-2012 18:35 от RXL » Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #13 : 06-05-2012 19:23 » 

RXL, в основе Ruby лежит Smalltalk. Концепции объектов и ссылок, а также блоков кода и символьных выражений - всё оттуда. Синтаксис, конечно, другой - более привычный основной массе программистов. Ну и сам подход к кодированию с минимумом "телодвижений" для достижения результата: "короткий разговор".

Я бы посоветовал не концентрировать внимание на мелочах, а, напротив, расслабиться и кодировать Улыбаюсь
« Последнее редактирование: 06-05-2012 19:25 от Dimka » Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
RXL
Технический
Администратор

Offline Offline
Пол: Мужской

WWW
« Ответ #14 : 24-05-2012 18:23 » 

Некоторой путаницей, но и удобным решением, является поведение локальных переменных в блоках {}. Передав такой блок в метод можно ссылаться на локальные переменные вызвавшего блока. По сути это замыкания.
Такой пример:

Код: (Ruby)
def func
  x = 2
  yield
end

x = 1
func { puts x }

Здесь будет распечатано "1".
Или более интересный пример:

Код: (Ruby)
table = [100, 200, 300]
puts([0, 2, 1].each {|x| table[x] }.join(', '))

Результат: "100, 300, 200".

Назревает вопрос, а нельзя ли использовать замыкания как в Perl, где ими создается эффект статических переменных?

Код: (Perl)
{
  $static_var = 1

  sub func
  {
    print "$static_var\n";
    $static_var++;
  }
}

Константы — это немного не то. Они доступны всему классу или модулю, а не одному методу.

Добавлено через 9 часов и 20 минут:
Управление доступом в Ruby вообще сплошная условность...


Не понял назначение фичи "class instance variable". Чем оно обосновывается и какое применение может иметь?
Вот пример из книги:

Код: (Ruby)
class Test
  @cls_var = 123
  def Test.inc
    @cls_var += 1
  end
end

Test.inc    # -> 124
Test.inc    # -> 125

И пример с атрибутом:

Код: (Ruby)
class Test
  @cls_var = 123
  class <<self
    attr_reader :cls_var
  end
end

Test.cls_var    # -> 123
« Последнее редактирование: 25-05-2012 03:54 от RXL » Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #15 : 25-05-2012 07:43 » 

Цитата: RXL
Назревает вопрос, а нельзя ли использовать замыкания как в Perl, где ими создается эффект статических переменных?
Есть же статические переменные с префиксом $ для функций в рамках модуля или класса. Ты сам их поминал выше. Причём тут блоки?
Код: (Ruby)
class C
  $x = 1
  def self.f
    puts $x
  end
end

C.f
Ну здесь ты вместо { ... } написал class ... end. А в чём ещё разница?

Я лично предпочитаю вместо фигурных скобок писать длиннее do ... end - то же самое, но мне кажется более эстетичным для длинных многострочных блоков. И вместо each использовать цикл for ... in ... (т.е. foreach) - опять же по эстетическим соображениям.

Код: (Ruby)
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

Цитата: RXL
Не понял назначение фичи "class instance variable". Чем оно обосновывается и какое применение может иметь?
Дословно это из Smalltalk. Обычный атрибут объекта (нестатическое поле), префикс @. Всегда private. Область видимости - объект (а не метод). Префикс $ описывает атрибут класса (статическое поле). Тоже private. Область видимости - класс. Она же - локальная переменная модуля с областью видимости в пределах модуля.

Назначение атрибутов объекта... Я думаю, это вопрос философский Улыбаюсь Однако все пользуются. Улыбаюсь
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
RXL
Технический
Администратор

Offline Offline
Пол: Мужской

WWW
« Ответ #16 : 25-05-2012 08:00 » 

С префиксом $ - это глобальные переменные. В рамках класса/модуля - с префиксом @@. Замыкание же делается для локальных переменных.

Цитата
Ну здесь ты вместо { ... } написал class ... end. А в чём ещё разница?

Кардинальная разница. Блок в Perl не является ни классом, ни модулем (что в Perl одно и тоже). И в нем можно определять локальные переменные. Не использовать общие локальные переменные метода или класса/модуля, а иметь свои.
Объясню поведение Perl в вышеприведенном примере. Блок {} объявлен в глобальном пространстве какого-либо модуля. Когда подгружается код модуля, происходит выполнение глобальных выражений и проверка функций. Внутри блока создается локальная переменная, которая используется в функции, определенной в этом же блоке и по этому при выходе из блока переменная не уничтожается, а создается замыкание, что сродни статической переменной. В модуле больше никому данная переменная не видна - только функциям внутри этого блока.


В общем, картина мира правила видимости переменных и управление доступом к ним в этих языках кардинально отличаются.

Добавлено через 12 минут и 34 секунды:
Цитата: RXL
Не понял назначение фичи "class instance variable". Чем оно обосновывается и какое применение может иметь?
Дословно это из Smalltalk. Обычный атрибут объекта (нестатическое поле), префикс @. Всегда private. Область видимости - объект (а не метод). Префикс $ описывает атрибут класса (статическое поле). Тоже private. Область видимости - класс. Она же - локальная переменная модуля с областью видимости в пределах модуля.

Назначение атрибутов объекта... Я думаю, это вопрос философский Улыбаюсь Однако все пользуются. Улыбаюсь

Нет-нет-нет. Дим, речь не о переменных объекта и атрибутах (суть есть переменная объекта + методы доступа). Там переменные именно класса, но класс рассматривается как объект.

Код: (Ruby)
class X
  @var = 100

  def self.var
    @var
  end

  def initialize
    @var = 200
  end

  def var
    @var
  end
end

Код: (Ruby)
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
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #17 : 25-05-2012 08:54 » 

Цитата: RXL
В рамках класса/модуля - с префиксом @@. Замыкание же делается для локальных переменных.
Правильно. Но в твоём Perl-коде описана функция и вне её - переменная, статическая для функции, и с ограниченной областью видимости. В моём примере сделано в точности то же самое. Без функции нет разговора о замыкании локальных переменных. Функции же в Ruby вне себя видят лишь переменные с префиксами @, @@, $, но не видят переменных без префиксов. О чём тогда вопрос?

Цитата: RXL
Кардинальная разница. Блок в Perl не является ни классом, ни модулем (что в Perl одно и тоже). И в нем можно определять локальные переменные. Не использовать общие локальные переменные метода или класса/модуля, а иметь свои.
Тут, как говорится: "Вам шашечки или ехать?" Т.е. тебе слово class не нравится в качестве блока для хранения переменных и функций?

Или же ты хочешь, чтобы внутри блоков Ruby можно было бы определять функции? Т.е. чтобы шли инструкции исполняемого кода, потом бац - функция, потом опять исполняемый код? А зачем? Для этого как раз и существуют блоки. Блоки анонимны (т.е. ведут себя как лямбда-функции), но поскольку они являются объектами, их можно хранить в переменных (т.е. именовать) и использовать как функции.

Код: (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, есть примеси.

Цитата: RXL
Объясню поведение Perl в вышеприведенном примере. Блок {} объявлен в глобальном пространстве какого-либо модуля. Когда подгружается код модуля, происходит выполнение глобальных выражений и проверка функций. Внутри блока создается локальная переменная, которая используется в функции, определенной в этом же блоке и по этому при выходе из блока переменная не уничтожается, а создается замыкание, что сродни статической переменной. В модуле больше никому данная переменная не видна - только функциям внутри этого блока.
По внешним признакам ты описал объект-синглетон. Ему соответствует класс или модуль Ruby со статическими переменными и статическими функциями. (Модуль в отличие от класса может иметь примеси других модулей.)

Цитата: RXL
Там переменные именно класса, но класс рассматривается как объект.
Не знаю, где "там", но в Ruby всё является объектами - и модули, и классы, и блоки кода. А что не так?
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
RXL
Технический
Администратор

Offline Offline
Пол: Мужской

WWW
« Ответ #18 : 25-05-2012 09:50 » 

Вопрос не шашечек. Просто примеряю Ruby на привычную картину мира, где есть статические переменные. Улыбаюсь


Цитата
Не знаю, где "там", но в Ruby всё является объектами - и модули, и классы, и блоки кода. А что не так?

Хочу понять, зачем это нужно. Побочный эффект или намеренное решение? Я именно о "class instance variable".
« Последнее редактирование: 25-05-2012 10:04 от RXL » Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #19 : 25-05-2012 11:45 » 

Цитата: RXL
Хочу понять, зачем это нужно. Побочный эффект или намеренное решение? Я именно о "class instance variable".
Не понимаю, о чём спрашиваешь. Зачем "зоопарк" из разных способов замыканий? Чтобы всем понравиться: в Ruby каждый пишет, как ему удобнее. Если народ привык к переменным экземпляра, то почему бы им не быть в языке?
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
Sla
Команда клуба

ua
Offline Offline
Пол: Мужской

WWW
« Ответ #20 : 25-05-2012 11:49 » 

> в Ruby каждый пишет, как ему удобнее.

Бред
Записан

Мы все учились понемногу... Чему-нибудь и как-нибудь.
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #21 : 25-05-2012 11:56 » 

Sla, ты пишешь, как тебе удобнее. Только зачем это навязывать остальным? Вон, Рома хочет, чтобы как в Perl было - вот и договариваемся о "типографских соглашениях" Улыбаюсь Как та же фигня в другом синтаксисе выглядит.
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
Sla
Команда клуба

ua
Offline Offline
Пол: Мужской

WWW
« Ответ #22 : 25-05-2012 12:00 » 

Но ведь кто-то это должен потом читать.
Записан

Мы все учились понемногу... Чему-нибудь и как-нибудь.
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #23 : 25-05-2012 12:18 » new

Sla, imho, если человек умеет читать Perl, он прочитает что угодно Улыбаюсь

Вот, к примеру, стиль бесклассового ООП в духе JavaScript на Ruby. Нечто похожее как раз и есть в Perl.
Код: (Ruby)
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 » Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines