Правила раздела:
1 Задавайте конкретные вопросы. Для болтовни есть свободный раздел.
2 По возможности давайте конкретные ответы.
3 Один вопрос=одна тема. Если хотите задать ещё вопрос, то начинайте новую тему.
4 Название темы должно составлять сам вопрос, и быть максимально конкретным. Рекомендуется начинать тему словами "Как", "Что", "Почему". А первый пост повторяет вопрос и даёт расширенные сведения.
5 Рекомендуется указывать версию мейкера (2000, 2003, RMXP, RMVX, ACE, IGM, и.т.д.. Это важно, и всё равно ведь спросят.
6 Темы "Пара вопросов", "Помогите", и подобные им - самый лёгкий путь к бану.
7 Поиск находится вверху справа.
А. Названия подразделов этого раздела уточняются. Советы принимаются.

Вопрос к скриптерам: alias и локальные переменные

Проект месяца 3 место Проект месяца 1 место Проект месяца 2 место 3 место Готв Победитель Сбитой кодировки Программист JavaScript 2 место Сбитая кодировка Писатель 3 место 2 место 3 место Организатор конкурсов
Больше
11 года 3 мес. назад #78057 от Cerberus
Вопрос такой. Имеется некоторая функция, внутри которой создаётся локальная переменная. Есть необходимость эту функцию дополнить, задействовав в дополнении эту локальную переменную. При переопределении через alias эта переменная становится локальной для alias-а, соответственно, код вида:
Code:
alias old_foo foo def foo old_foo for i in bar dosomething(i) end end
где bar - массив, созданный в функции old_foo, т.е. в прежней реализации foo, - такой код уже не работает (переменная bar не существует). Можно ли это как-то обойти, не переопределяя полностью исходную функцию?

Жуть болотная, на лапках, в тапках и с пулемётом...

Пожалуйста Войти или Регистрация, чтобы присоединиться к беседе.

3 место Готв Программист JavaScript Разработчик Проект месяца 2 место 2 место Готв
Больше
11 года 3 мес. назад - 11 года 3 мес. назад #78060 от sinder
Насколько я понял эти alias-ы, то дописанный код в них, добавляется в конец метода, соответственно если пытаться вызвать переменную определенную с помощью alias-a раньше чем она создается, то получим что она не существует. Поэтому думаю, что без переписывания всего метода не обойтись. Хотя может я и не прав.
Последнее редактирование: 11 года 3 мес. назад пользователем sinder.

Пожалуйста Войти или Регистрация, чтобы присоединиться к беседе.

Проект месяца 3 место Проект месяца 1 место Проект месяца 2 место 3 место Готв Победитель Сбитой кодировки Программист JavaScript 2 место Сбитая кодировка Писатель 3 место 2 место 3 место Организатор конкурсов
Больше
11 года 3 мес. назад #78061 от Cerberus
Нет, в примере же видно, что я сначала вызываю оригинал (алиаснутый), а потом пытаюсь использовать переменную, "сидящую" внутри него.

Жуть болотная, на лапках, в тапках и с пулемётом...

Пожалуйста Войти или Регистрация, чтобы присоединиться к беседе.

Программист Ruby Организатор конкурсов Даритель Стимкея 2 место Сбитая кодировка Переводчик 2 место
Больше
11 года 3 мес. назад #78066 от strelokhalfer
Ты вызываешь оригинал, он отрабатывает и удаляет локальные переменные.
Хотя, попробуй в имени методов добавить *args и &block

"Стрелок, что-то ты неочень похож на свой аватар..."(с)

Пожалуйста Войти или Регистрация, чтобы присоединиться к беседе.

Проект месяца 3 место Проект месяца 1 место Проект месяца 2 место 3 место Готв Победитель Сбитой кодировки Программист JavaScript 2 место Сбитая кодировка Писатель 3 место 2 место 3 место Организатор конкурсов
Больше
11 года 3 мес. назад #78067 от Cerberus
А что это изменит? Пытаюсь понять механику предложенного...

Жуть болотная, на лапках, в тапках и с пулемётом...

Пожалуйста Войти или Регистрация, чтобы присоединиться к беседе.

Программист Ruby Организатор конкурсов Даритель Стимкея 2 место Сбитая кодировка Переводчик 2 место
Больше
11 года 3 мес. назад - 11 года 3 мес. назад #78068 от strelokhalfer
ВРоде эти параметры передают из метода все локальные данные.
Code:
def old a = "a" end alias new old def old(*args, &block) new(*args, &block) a = "b" end

Проверить не могу, пока не дома.

"Стрелок, что-то ты неочень похож на свой аватар..."(с)
Последнее редактирование: 11 года 3 мес. назад пользователем strelokhalfer.

Пожалуйста Войти или Регистрация, чтобы присоединиться к беседе.

Проект месяца 3 место Проект месяца 1 место Проект месяца 2 место 3 место Готв Победитель Сбитой кодировки Программист JavaScript 2 место Сбитая кодировка Писатель 3 место 2 место 3 место Организатор конкурсов
Больше
11 года 3 мес. назад #78069 от Cerberus
Нет, к сожалению, не сработало. Получить значение переменной a после вызова new таким образом не удалось.

Жуть болотная, на лапках, в тапках и с пулемётом...

Пожалуйста Войти или Регистрация, чтобы присоединиться к беседе.

Программист Ruby 2 место Готв Победитель Сбитой кодировки Учитель Оратор
Больше
11 года 3 мес. назад - 11 года 3 мес. назад #78075 от Amphilohiy
Все, что произошло на Миле, остается на Миле. Это закон.

Но можно попытаться сделать bar в виде переменной инстанса за счет функций.
Code:
def bar @bar end def bar=(arg) @bar=arg end

По необходимости обнулять.

Я верю, что иногда компьютер сбоит, и он выдает неожиданные результаты, но остальные 100% случаев это чья-то криворукость.
Последнее редактирование: 11 года 3 мес. назад пользователем Amphilohiy.
Спасибо сказали: Cerberus, Ren310

Пожалуйста Войти или Регистрация, чтобы присоединиться к беседе.

Проект месяца 3 место Проект месяца 1 место Проект месяца 2 место 3 место Готв Победитель Сбитой кодировки Программист JavaScript 2 место Сбитая кодировка Писатель 3 место 2 место 3 место Организатор конкурсов
Больше
11 года 2 мес. назад - 11 года 2 мес. назад #78077 от Cerberus
Сделал для начала вот так:
Code:
class Testing def hit @hit end def hit=(value) p value @hit=value end def initialize hit = [] p @hit end end

Testing.new выдаёт nil.

upd: нашёл ошибку. Если в инициализации hit заменить на self.hit, то всё работает как надо. Но это сейчас, к сожалению, не подходит.

Жуть болотная, на лапках, в тапках и с пулемётом...
Последнее редактирование: 11 года 2 мес. назад пользователем Cerberus.

Пожалуйста Войти или Регистрация, чтобы присоединиться к беседе.

Программист Ruby Ветеран Даритель Стимкея Оратор Программист JavaScript
Больше
11 года 2 мес. назад #78078 от Lekste
В инициализации hit попробуй с собакой написать, а не как локальную

Пожалуйста Войти или Регистрация, чтобы присоединиться к беседе.

Проект месяца 3 место Проект месяца 1 место Проект месяца 2 место 3 место Готв Победитель Сбитой кодировки Программист JavaScript 2 место Сбитая кодировка Писатель 3 место 2 место 3 место Организатор конкурсов
Больше
11 года 2 мес. назад #78079 от Cerberus
Так инициализация здесь как пример процедуры, которую я менять не вправе. Но уже вроде понял, что это нерешаемо.

Жуть болотная, на лапках, в тапках и с пулемётом...

Пожалуйста Войти или Регистрация, чтобы присоединиться к беседе.

Программист Ruby 2 место Готв Победитель Сбитой кодировки Учитель Оратор
Больше
11 года 2 мес. назад #78080 от Amphilohiy
Посмотрел, да, не пашет. Этот принцип работает, только если явно обратиться к классу (self.hit=...), но явно такой метод не катит.
Я тут нашаманил, пока думал какие могут быть альтернативы. Прячьте детей и беременных женьщин.
Code:
#Наш класс class Foo #Старая функция. Неприступная как шут знает что. def bar value = 5 end #Алиасим и переопределяем alias bar1 bar def bar #Вызываем старую функцию. Трейсер ниже ловит ее и выхватывает биндинг bar1 #В биндинге недавно вызванной функции делаем новое вычисление, а именно спрашиваем локальную переменную value = $bind.eval("value") #Ваш код #... #Возврат для проверки value end end #Трейсер. Выхватывает вообще все действия в Руби, включая вызов функции set_trace_func proc { |event, file, lineno, id, binding, klass| #События вызова функции. Второе условие важно, вместо Foo впихните свой класс. if (event == "call") and (klass <= Foo) then #Складируем биндинг для будующего использования. Например в $bind $bind = binding end } #Пускаем тест foo = Foo.new p foo.bar
Идея в 2 словах - создаем функцию трейсер, которая обрабатывает почти любое действие в Руби. Ставим ленивые "и" условия на наш класс и его производные (можно было бы добавить "and (id == :bar)" для конкретной функции). Там ловим биндинг (читай поле видимости) и складируем в глобальное пространство. Затем производим расчет в биндинге и получаем нужные значения.
Вроде все пашет бодренько, но за падение производительности, лично я, боюсь. Магия темная, в практике раньше не использовал. Ну и в реализации могут быть траблы.

Я верю, что иногда компьютер сбоит, и он выдает неожиданные результаты, но остальные 100% случаев это чья-то криворукость.
Спасибо сказали: Iren_Rin

Пожалуйста Войти или Регистрация, чтобы присоединиться к беседе.

Программист Ruby Ветеран Даритель Стимкея Оратор Программист JavaScript
Больше
11 года 2 мес. назад #78081 от Lekste
По-хорошему такого быть вообще не должно. Давай конкретный пример - подумаем как сделать иначе.

Пожалуйста Войти или Регистрация, чтобы присоединиться к беседе.

Проект месяца 3 место Проект месяца 1 место Проект месяца 2 место 3 место Готв Победитель Сбитой кодировки Программист JavaScript 2 место Сбитая кодировка Писатель 3 место 2 место 3 место Организатор конкурсов
Больше
11 года 2 мес. назад #78082 от Cerberus
Весело, действительно. Хотя, если я решу побаловаться с этим самым трейсером на ещё какую-то тему, может, оно и нормально получится... А у меня там вот такой вот кусок модуля: pastebin.com/9DZXwNs7 (здесь я пытался задействовать идею, предложенную выше). Модуль потом импортируется в класс.

Жуть болотная, на лапках, в тапках и с пулемётом...

Пожалуйста Войти или Регистрация, чтобы присоединиться к беседе.

Программист Ruby Коммерсант Проект года 1 место Учитель Проект месяца 1 место
Больше
11 года 2 мес. назад - 11 года 2 мес. назад #78244 от Iren_Rin
Я как первый раз прочитал тему пробовал всякое, чтобы получить binding оригинального метода, но до set_tracer_func так и не дошел. И это настоящая темная сторона, спасибо Амфи :)
Представлю свой код, который позволит получить локальные переменные оригинального метода, и при этом не тормозить весь стэк руби. Идея в том, чтобы установить трейсер только на время вызова оригинального метода, а потом обнулить его.
Code:
def say a = 1 end alias original_say say def say aliased_binding = nil #заводим переменную, чтобы иметь к ней доступ из трейсера tracer = proc do |event, file, lineno, id, binding, klass| aliased_binding = binding if event == 'return' #записываем в заведенную переменную binding после исполнения оригинальной функции end set_trace_func tracer #устанавливаем трейсер original_say set_trace_func nil #обнуляем трейсер, незачем ему вечно тормозить наш код aliased_binding.eval 'a' end say
Последнее редактирование: 11 года 2 мес. назад пользователем Cerberus.
Спасибо сказали: Cerberus, Ren310, strelokhalfer, Amphilohiy

Пожалуйста Войти или Регистрация, чтобы присоединиться к беседе.

Проект месяца 3 место Проект месяца 1 место Проект месяца 2 место 3 место Готв Победитель Сбитой кодировки Программист JavaScript 2 место Сбитая кодировка Писатель 3 место 2 место 3 место Организатор конкурсов
Больше
11 года 2 мес. назад #78247 от Cerberus
Спасибо! Всё отлично работает. Не знаю, правда, буду ли я это прикручивать к скрипту, который закинул в pastebin, но освоить этот самый трейсер будет в любом случае интересно. И для отладки в том числе :)

Жуть болотная, на лапках, в тапках и с пулемётом...

Пожалуйста Войти или Регистрация, чтобы присоединиться к беседе.

Программист Ruby 2 место Готв Победитель Сбитой кодировки Учитель Оратор
Больше
11 года 2 мес. назад - 11 года 2 мес. назад #78248 от Amphilohiy
Звучит замечательно! Я не проверял обнуление, но если не ошибаюсь, то на объект можно навесить тонну финализаторов, по одному за вызов функции (в тех экспериментах со слабыми ссылками). Побоялся, что тут может произойти та же история, и руки так не дошли.

Самое веселое, я сейчас даже немного не понимаю как твой код работает :( поэтому тоже пока не проверю.

UPD: Ложная тревога. Проверил, трейсер обнуляется, а я с позором ухожу со светлой еще на месяц :P . А не понял как работает код по той причине, что все описано вне класса, что сбивало меня с толку.
И для совсем любопытных сама проверка
ВНИМАНИЕ: Спойлер!

Я верю, что иногда компьютер сбоит, и он выдает неожиданные результаты, но остальные 100% случаев это чья-то криворукость.
Последнее редактирование: 11 года 2 мес. назад пользователем Amphilohiy.

Пожалуйста Войти или Регистрация, чтобы присоединиться к беседе.

Время создания страницы: 0.129 секунд
Работает на Kunena форум