Форум Flasher.ru
Ближайшие курсы в Школе RealTime
Список интенсивных курсов: [см.]  
  
Специальные предложения: [см.]  
  
 
Блоги Правила Справка Пользователи Календарь Поиск рулит! Сообщения за день Все разделы прочитаны
 

Вернуться   Форум Flasher.ru > Блоги > JackFromChaos

Оценить эту запись

Универсальная замена анонимных функций и не только...

Запись от JackFromChaos размещена 25.01.2011 в 03:52
Обновил(-а) JackFromChaos 25.01.2011 в 05:36

Собственно, класс способный заменить замыкание, да и вообще может быть весьма полезным... С моей точки зрения, естественно...
Код AS3:
package utils 
{
	/**
	 * ...
	 * @author Denis `Jack` Vinogradsky
	 */
	public class Callback 
	{
		private var _callback:Function;
		private var _params:Array;
 
		public function execute():void
		{
			if (_callback == null)
				return;
			_callback.apply(null, _params);
		}
		public function Callback(callback:Function,...rest) 
		{
			_params = rest;
			_callback = callback;
		}
 
	}
 
}
После исправлений, класс стал совсем маленьким, что не может не радовать.
Всего комментариев 41

Комментарии

Старый 25.01.2011 04:30 iNils вне форума
iNils
 
Аватар для iNils
В default ошибка в конце: ..._params[14],_params[15],,_params[15]);
Старый 25.01.2011 05:11 andrew911 вне форума
andrew911
Кстати, вместо кучи case-ов можно использовать:
Код AS3:
_callback.apply( null, _params);
http://www.ericfeminella.com/blog/20...een-functions/
Старый 25.01.2011 05:34 JackFromChaos вне форума
JackFromChaos
 
Аватар для JackFromChaos
Спасибо за подсказку.
Упростил, убрал функцию release(проверил, убедился, что если на нее никто не ссылается, она прекрасно собирается...)
Старый 25.01.2011 08:19 i.o. вне форума
i.o.
 
Аватар для i.o.
На мой взгляд лучше переименовать Callback -> Delegate. Ближе по смыслу.
Старый 25.01.2011 11:05 ChuwY вне форума
ChuwY
 
Аватар для ChuwY
Нубский вопрос: а замыкание по-твоему принципиально не должно ничего возвращать?
Старый 25.01.2011 12:09 Psycho Tiger вне форума
Psycho Tiger
 
Аватар для Psycho Tiger
Хочется пример использования, на котором было бы видны его удобства.
Старый 25.01.2011 12:45 BlooDHounD вне форума
BlooDHounD
 
Аватар для BlooDHounD
это обёртка вокруг apply?
Старый 25.01.2011 12:48 JackFromChaos вне форума
JackFromChaos
 
Аватар для JackFromChaos
2ChuwY: Да, в моем понимании, это правильно. Ситуации когда callback может потребовать возвращаемый результат, редкость. И, вероятно, очень специфичны. Для тех случаев я бы, скорее всего сделал отдельный класс, причем, скорее всего с типизированным возвращаемым результатом.
Но если хочется, вам никто не мешает написать так:
Код AS3:
		public function execute():*
		{
			if (_callback == null)
				return;
			return _callback.apply(null, _params);
		}
2i.o.:
Я думал над этим с самого начала, но все таки в моем понимании делегат - это указатель на функцию... Т.е. для делегата мне бы пришлось передавать в execute параметры. По большому счету это вообще вариант реализации паттерна Command... Но называть ее так тоже не хочеть....
Старый 25.01.2011 12:50 JackFromChaos вне форума
JackFromChaos
 
Аватар для JackFromChaos
2BlooDHounD: Почти... Он позволяет полностью избавить от замыкания на основе анонимных функций. Да и в других случаях может быть полезен. Отличие от класса Function, эта функция хранит параметры....
Старый 25.01.2011 12:56 JackFromChaos вне форума
JackFromChaos
 
Аватар для JackFromChaos
2Psycho Tiger:
Реализации функционалов подобных setTimeout.
При реализации классов на основе паттерна Command.
Так же, вот простой, урезанный, глобального менеджера горячих клавиш. Это не настоящий пример, но общий смысл уловить можно:
Код AS3:
		private var _keys:Dictionary = new Dictionary();
		public function registerKey(keyCode:uint, callback:Callback):void
		{
			_keys[keyCode] = callback;
		}
		private function onKeyDown(e:KeyboardEvent):void
		{
			var callback:Callback = _keys[e.keyCode] as Callback;
			if (callback)
				callback.execute();
		}
Старый 25.01.2011 13:08 alatar вне форума
alatar
 
Аватар для alatar
Цитата:
Он позволяет полностью избавить от замыкания на основе анонимных функций.
Каким образом?
Цитата:
Да и в других случаях может быть полезен.
Хоть один приведите.
Цитата:
Отличие от класса Function, эта функция хранит параметры....
Зачем это может понадобиться? Тем более, что поменять их не получится.
Старый 25.01.2011 13:45 JackFromChaos вне форума
JackFromChaos
 
Аватар для JackFromChaos
Каким образом?
хм... таким же, каким его реализуют анонимные функции... если нужен пример, могу написать вечером, сейчас как бы работать надо...

Хоть один приведите.
Примеры "зачем" - написано сразу над вашим постом...

Зачем это может понадобиться? Тем более, что поменять их не получится.
Так и задумывалось...
Старый 25.01.2011 14:00 BlooDHounD вне форума
BlooDHounD
 
Аватар для BlooDHounD
он не позволяет избавится от анонимных функций. он переносит их на другой уровень.
Старый 25.01.2011 14:05 JackFromChaos вне форума
JackFromChaos
 
Аватар для JackFromChaos
2BlooDHounD: В принципе - да... Но говорят, что в AS3 анонимными функциями пользоваться нельзя... А механизм полезный... Только не надо начинать спорить, о вреде "анонимных функций"... Если вам это не нужно, ну и не пользуйтесь... Только не нужно разжигать очередной холивар...
Старый 25.01.2011 14:28 Psycho Tiger вне форума
Psycho Tiger
 
Аватар для Psycho Tiger
JackFromChaos, да не у меня вопрос. А в статью это добавить, т.к. не очевидно.

А вообще упёртость автора заслуживает уважения. Давайте посмотрим, кто знает, может он наш мессия.
Старый 25.01.2011 14:32 BlooDHounD вне форума
BlooDHounD
 
Аватар для BlooDHounD
@JackFromChaos, я не разжигаю. я говорю, что ваш класс не убирает и не упрощает их использования вообще никаким боком.

@Psycho Tiger, угу. вон в разделе АС3 мессиит по полной =)
Старый 25.01.2011 21:40 f.g.programmer вне форума
f.g.programmer
 
Аватар для f.g.programmer
Такой подход позволяет избавиться от анонимных функций везде, где они могут показаться полезными.
Я выкладывал похожий класс в начале этого года в своей записи про SEC, у меня он выглядел так
Код AS3:
package
{
   public class Action
   {
       /// создание функуии с меньшим количеством параметров или без, подстановка в том же порядке в конец
       public static function create(fun:Function, ...params):Function {
           return new Action(fun, params).call;
       }
 
       private var _fun:Function;
       private var _args:Array;
       public function Action(fun:Function, args:Array)
       {
           _fun = fun;
           _args = (args) ? args.slice() : [];
       }
       public function call(...args):* {
           return _fun.apply(null, args.concat(_args));
       }
   }
}
Старый 25.01.2011 22:52 BlooDHounD вне форума
BlooDHounD
 
Аватар для BlooDHounD
нет не позволяет. это один из способов их псевдозамены, но никак не способ избавления от них. таких способов чуть больше чем бесконечность. но они не избавляют от замыканий. они просто заставляют писать код иначе. с большой доле вероятности, из особенности мышления, люди будут использовать ваш классе вместе с замыканиями, и будет получаться что-то типа
Код AS3:
Action.create(function(){});
что бы отучить людей использовать замыкания, надо научить их иначе мыслить. никакой класс им в это не поможет.
Старый 26.01.2011 03:36 JackFromChaos вне форума
JackFromChaos
 
Аватар для JackFromChaos
Не нужно отучать людей использовать замыкание. Это нормальный механизм программирования. Вопрос может стоять, как его лучше реализовывать, но не как от него избавиться...
Старый 26.01.2011 03:48 iNils вне форума
iNils
 
Аватар для iNils
Нужно, нормального в нем ничего нет.
Обновил(-а) iNils 26.01.2011 в 03:50
Старый 26.01.2011 03:55 JackFromChaos вне форума
JackFromChaos
 
Аватар для JackFromChaos
Класс
Не знаю, может потому что это фича языка... Которой радуются, когда она появляется в языке(c# 2.0), которую пишут как преимущество при описании языка программирования... Которую эмулируют на языках, замыкание не придерживающие...

Собственно, единственное место, где его почему то все ругают, это данный форум...

А весь остальной мир этим активно пользуется.

А еще может потому, что мы стоим на пороге функционального программирования, и вполне вероятно, рано или поздно, столкнемся с ним вплотную....

Не знаю что тут ответить... Можно было бы спросить, а что плохого? Но даже не хочу...

Я уже понял, что достаточно наступить пару раз на какие нибудь грабли, что бы решить... Аха, я тут на грабли наступил, плохо... Этим пользоваться нельзя....
Старый 26.01.2011 04:00 iNils вне форума
iNils
 
Аватар для iNils
Цитата:
Не знаю что тут ответить... Можно было бы спросить, а что плохого? Но даже не хочу...
Наверно потому, что не знаете что в этом хорошего. Просто используете, не задумываясь, потому что привыкли.
Кстати, про плохое Блуд уже не раз писал.
Старый 26.01.2011 04:34 JackFromChaos вне форума
JackFromChaos
 
Аватар для JackFromChaos
Что хорошего в паттерне command?

по поводу того, что плохого в замыкании... нашел вот только про анонимные функции от Блуда... Я так понимаю, тут это и имеется ввиду. Итак, по пунктам:


анонимные функции:
1. создаются каждый раз при попадании в функцию родитель.
Не когда заходят в функцию, а когда доходят до места, где она декларируется. То что EventDispatcher не подписывают 2 раза подрят одну и ту же функцию, не значит, что вызывать многократно функцию init которая на что-то подписывается – красивый код... То, что Adobe сделала защиту от дурака, не значит что надо себя вести как...
Опять же, класс который я привел вполне управляем, все можно создавать тогда и столько раз, сколько надо... Хотя с анонимами тоже можно это вполне проделать, если голову включить.

2. имеют кривую типизацию.
Не более кривую, чем эвенты. Да, адоба придумала для нас стандартную сигнатуру для эвента. Никто не мешает ввести у себя дополнительный стандарт на какие то свои колбэки. Мехнизмы теже... Типизация та же...

3. жрут больше памяти.
Приведенный класс эту проблему решает. Кстати, анонимы кроме того что жрут больше, работают в 25 быстрее чем эвент.

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

5. от них проблемно отписываться.
Проблемно, но можно. Опять же, данный класс решает эту проблему...

6. их нельзя сравнивать друг с другом.
Ни разу в жизни не сравнивал указатели на функции. Попахивает какой то магией...

и т.д. и т.п.
Пока, как бы не нашел адекватных причин, что плохо...

Замыкание держат ссылку и не дают нормально работать коллектору? Есть множество способов держать ссылку не давая объекту удалиться. Вопрос здесь не механизма замыкания, а кривизны рук программиста.
Обновил(-а) JackFromChaos 26.01.2011 в 04:36
Старый 26.01.2011 04:50 JackFromChaos вне форума
JackFromChaos
 
Аватар для JackFromChaos
Извините, в пункте 2, имелось ввиду немного другое, чем то, на что я ответил(в голове был спор Блуда о бесполезности сигналов...)
Да, анонимные функции действительно немного странно работают с типизацией. Вышеприведенный класс решает эту проблему...
Старый 26.01.2011 05:08 JackFromChaos вне форума
JackFromChaos
 
Аватар для JackFromChaos
Если под "замыканием" понимается исключительно "анонимная функция", то извините, был не прав... Анонимными функциями лучше в AS3 не пользоваться, безусловно. Т.е. они не так страшны как из расписывают, но множество подводных камней, на которые по не знанию можно напороться... Тут не спорю.
Но причем тут изменения мышления? Если под замыканием понимать более общее понятие:
"Замыкание (англ. closure) в программировании — процедура, которая ссылается на свободные переменные в своём лексическом контексте.
Замыкание, так же как и экземпляр объекта, есть способ представления функциональности и данных, связанных и упакованных вместе." То в этом плохого ничего нет. И класс вверху вполне решает многие из задач, которые может захотеться решить анонимными функциями. По сути являющиеся механизмом «замыкание», по словам того же Блуда...
Обновил(-а) JackFromChaos 26.01.2011 в 05:10
Старый 26.01.2011 05:19 iNils вне форума
iNils
 
Аватар для iNils
Как я и ожидал, аргументы размыты и сводятся к тому, что можно подумать, решить и избежать, вот только смысла это делать, я так и не увидел.
Единственная конкретика была в пункте 3, но... быстрее в каком плане, и откуда данные про 25 раз?

PS. Я с детства не люблю теорию оторванную от практики. Любой практик заткнет за пояс теоретика, который замыкается на теории без примеров практического применения.
Обновил(-а) iNils 26.01.2011 в 05:23
Старый 26.01.2011 05:24 JackFromChaos вне форума
JackFromChaos
 
Аватар для JackFromChaos
В общем, прошу всех прощения, если где-то был резок, и завязываю с холиварными темами. Постараюсь в таковых больше не участвовать. Все это не конструктивно, при этом, отнимает время... Вместо того, что бы сделать что-то полезное, занимаюсь фигней уже наверное 3 часа. А это глупо...

По поводу вышеприведенного класса. Если скажете что он не правильный, и использовать его нельзя, могу удалить этот блог. Или пусть это сделают модераторы. Мне все равно.
Старый 26.01.2011 05:43 JackFromChaos вне форума
JackFromChaos
 
Аватар для JackFromChaos
Просто отвечаю на вопрос, зачем мне нужен вышеприведенный класс.
Данный класс использую в своем глобальном менеджере горячих клавиш. Псевдо пример был в комментариях выше.
Использую как один из способов реализации Command. Т.е. как один из потомков базовой команды, в данный момент, для построения редактора уровней.
Этот класс появился только сейчас. Но я вообще активно использую механизмы аля Action. И класс вполне мог там пригодится.
Думаю применять его в большинстве случаев, вместо указателей на функции (callback). А их я использую часто.(спорить о преимуществах и недостатках callback-ов больше не желаю).
Так же, по мере необходимости, когда возникает потребность...
Допускаю написание похожего класса для универсальной реализации подписки его на собятие. Грубо говоря, изменения сигнатуры execute():void на execite(e:Event):void. Но вопрос пока висит, так как собираюсь перед реализацией учесть возможные проблемы с висящими ссылками. Думаю, проблемы решу. Но это на досуге... Обсуждать это тему так же не желаю, так как уже отсюда вижу во что превратится это обсуждение. Постить данныцй класс сюда, так же, вероятно, не буду. По тем же причинам.
Старый 26.01.2011 11:54 BlooDHounD вне форума
BlooDHounD
 
Аватар для BlooDHounD
JackFromChaos, вы зациклились на вашем классе, на который тут ваще всем пофигу. лично мне непонятно какое отношение к нему имеют анонимные функции. и какую замену он несёт. а то вас уже занесло в спор "докозатьхотьчавоэтимснобам". я вот сейчас могу заморочиться и оспорить все пункты в вашем полотне, кроме первого, но мне хочется что бы вы сами подумали почему в 5 из 6 пунктов вы не правы.
Старый 26.01.2011 12:36 JackFromChaos вне форума
JackFromChaos
 
Аватар для JackFromChaos
2BlooDHounD:

5 и 6 пункт – суть одна проблема. Причем 5-й не имеет отношение к AS3.
Анонимная функция а точнее даже «замыкание», это способ «создавать функции». Логично, что каждый раз, когда мы создаем функцию, она имеет новый указатель.
Каждый раз, когда мы создаем new Point, мы тоже создаем новый указатель.
И естественно проблема, если мы хотим сделать например так:
Код AS3:
function test():Sprite
{
	return new Sprite();
}
 
addChild(test());
removeChild(test());//Вот блин, здесь почему то не удаляется… отстой какой то…;)
А указатель на метод... Ну это как свойство:
Код AS3:
var _test:Sprite=new Sprite();
function test():Sprite
{
	return _test;
}
 
addChild(test());
removeChild(test());
Нельзя ведь сказать что в вышеприведенных примерах работает что-то не так? Ну так вот, тоже и с анонимными функциями. Это не баг, это фича.

Пункта 6 в равной степени касается все что написано выше + отсутствие возможности перегрузки оператора сравнения.

Мне вот не нравится, что я не могу сравнить две точки:
Код AS3:
var p1:Point = new Point(1, 1);
var p2:Point = new Point(1, 1);
trace(p1 == p2)
trace(p1 === p2);
var s1:String = new String("text");
var s2:String = new String("text");
trace(s1 == s2)
trace(s1 === s2);
А строки могут… Может пора отказаться от точек в пользу строк?
Старый 26.01.2011 13:51 BlooDHounD вне форума
BlooDHounD
 
Аватар для BlooDHounD
не 5 и 6, а 5 из 6.
у вас в голове каша. вы не создаёте указатель. вы создаёте ссылку.
не понятно как ваши примеры относятся моим высказываем. и где вы там увидели слово баг? это фича, которую надо понимать. вы это понимаете - хорошо. а про пункт 6, вы непонятно что написали. я вам совету прекратить писать и начать понимать, что вам пытаются донести. сперва мне было весело, а теперь грустно.
Старый 26.01.2011 14:03 JackFromChaos вне форума
JackFromChaos
 
Аватар для JackFromChaos
Аха, расскажите мне, в чем разница между словами "ссылки" и "указатель"... Хотя, нет, нет стоит... Для меня ссылка и указатель в AS3 синонимы(они для меня обозначают разное в c++, но даже там, я знаю, что это все равно одно и тоже, только синтаксис разный)... извините, если не правильно обращаюсь со словами...
Про пункт 6 вы писали:
6. их нельзя сравнивать друг с другом.
Код AS3:

Код AS3:
function test():Function {
	return function() {
		return 0;
	}
}
trace( test() === test() ) // false;
trace( test === test ); // true
Во первых, это тоже самое, что написать:
Код AS3:
function test():Point {
   return new Point(1,1);
 
}
trace( test() === test() ) // false;
trace( test === test ); // true
Но, скажем, на примере того же поинта, если бы была возможность перегружать операторы, можно было бы написать что-то типа:
Код AS3:
public function eq(p:Point):Boolean
{
   return this.x==p.x&&this.y==p.y;
}
Собственно функцию такую написать то можно, только сравнение будет немного не стандартным.
Что-то похожее можно реализовать и для класса Callback.

К сожалению, похоже не понимаете вы... Но не суть... Я уже говорил, что спор бесполезен... Потому предлагаю с этим заканчивать...
Старый 26.01.2011 14:09 ChuwY вне форума
ChuwY
 
Аватар для ChuwY
Извините за некоторый оффтоп. Но раз тут сбежались гуру и негуру, то не могу их упустить.

Код AS3:
function makePow(x : int):Function{
  return function(y : int):int{
    return Math.pow(x, y);
  }
}		  
 
var fiveInDegree : Function = makePow(5);
var fiveQquared  : int = fiveInDegree(2);
 
trace("fiveQquared = " + fiveQquared); // 25
 
fiveInDegree = null;
После выполнения такого кода никаких ссылок лишних не должно остаться и можно реализовывать каррирование без дрожи в коленях из-за замыканий-и-анонимных-функций?
Старый 26.01.2011 14:13 BlooDHounD вне форума
BlooDHounD
 
Аватар для BlooDHounD
я укрепляюсь в том что у вас каша в голове. в контекста VM слово указатель не значит ничего. а если вы знаете разницу в срр, то видимо понимаете, что дело не в синтаксисе. слова должны иметь контекст, а не быть просто красивыми.
вы сколько угодно можете писать ненужные примеры, пока не расскажете мне цель всего этого. вы пытаетесь доказать, что облака высоко, в то время как мы разговаривает о цвете траве. самое смешное, что с вами никто не спорит.
Старый 26.01.2011 14:16 BlooDHounD вне форума
BlooDHounD
 
Аватар для BlooDHounD
ChuwY, да всё что угодно можно. например, можно корову доить прищепками.
Старый 26.01.2011 14:18 ChuwY вне форума
ChuwY
 
Аватар для ChuwY
BlooDHounD, я в споры не ввязывался, ни с кем (просто хочу лучше узнать тему на конкретном примере) и прошу ответить мне с чуть меньшей долей сарказма, если тебя не затруднит
Старый 26.01.2011 14:19 JackFromChaos вне форума
JackFromChaos
 
Аватар для JackFromChaos
2ChuwY:Не должно, и не останется...

2BlooDHounD: Отлично, у меня в голове каша. На этом и остановимся...
Просто вы говорите, что нельзя пользоваться замыканием, и перечисляете фичи. Я говорю, что надо понимать фичи, и тогда можно пользоваться...
Старый 26.01.2011 14:40 BlooDHounD вне форума
BlooDHounD
 
Аватар для BlooDHounD
ChuwY, а повторю: ответственность за реализацию чего угодно лежит на плечах разработчика. нет правильных и не правильных способов. есть практичные и непрактичные.

JackFromChaos, я не говорил "нельзя". я говорил "почему не стоит". я сам пользовался неоднократно в случаях крайней нужды, но я прекрасно понимаю все нюансы. собственно их я и описал. если человек говорит, что болгарка очень опасная, и даёт большой талмуд о технике безопасности, он пытается вас уберечь от потери руки, но ему абсолютно пофигу будете ли вы пользоваться болгаркой вместо молотка.
Старый 26.01.2011 14:46 JackFromChaos вне форума
JackFromChaos
 
Аватар для JackFromChaos
Ну вот и разобрались. За сим считаю спор законченным.
Старый 26.01.2011 15:18 JackFromChaos вне форума
JackFromChaos
 
Аватар для JackFromChaos
2ChuwY:
Более того, данный код совсем не помешает работе коллектора, и все прекрасно соберется, если мы больше нигде не сохраним ссылку на spr и никуда его не добавим.
Код AS3:
var spr:Sprite = new Sprite();
spr.addEventListener(MouseEvent.CLICK, function(e:Event):void { spr.visible = false; } );
Обновил(-а) JackFromChaos 26.01.2011 в 15:24
Старый 27.01.2011 21:27 dimarik вне форума
dimarik
 
Аватар для dimarik
Код, состоящий в своей массе из callback очень сложен в понимании и отладке. Очень неприятно обслуживать подобные проекты.
 

 


Часовой пояс GMT +4, время: 19:58.


Copyright © 1999-2008 Flasher.ru. All rights reserved.
Работает на vBulletin®. Copyright ©2000 - 2024, Jelsoft Enterprises Ltd. Перевод: zCarot
Администрация сайта не несёт ответственности за любую предоставленную посетителями информацию. Подробнее см. Правила.