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

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

Рейтинг: 5.00. Голосов: 3.

Макросы Haxe. Вводная статья.

Запись от Dima_DPE размещена 06.05.2013 в 15:18

Цитата:
Все ниже написанное соответствует Haxe 2 и почти верно для Haxe 3. Но работать без изменений будет только во 2-м. Кто адаптирует все примеры на 3-й и поделится с остальными, получит много экспириенса. Так же написанное не претендует на истину в последней инстанции и может содержать ошибки.
Хочу немного рассказать о макросах в Haxe, статья будет именно вводная, попробую рассказать и показать зачем вообще нужны макросы и какие задачи они могут решать в повседневной жизни.
Макросы в Haxe используют неоправданно мало программистов, кого-то отпугивает их синтаксис, кто-то просто не знает, что это и зачем. Все возможности макросов отлично описаны в статье метапрограммирование на википедии. В двух словах скажу: макросы позволяют как модифицировать существующий код (самомодификация кода), так и создавать новый (генерация кода). В этой статье мы попробуем генерировать новый код, но в очень ограниченных масштабах. Такие вещи, как генерация классов или enum-ов или редактирование существующего кода, я не затрону, лишь замечу, что все это возможно в пределах Haxe макросов!

Так что же на самом деле макрос в Haxe? Вы не поверите, но макросы это обычные функции. Ну не совсем обычные, но и ничего незнакомого по сравнению с кодом Haxe в них нет. Главные плюсы макросов - это то, что в них, кроме стандартной библиотеки, доступны еще и все классы пакетов neko и haxe.macro и то, что функции-макросы вызываются на этапе компиляции, а не во время выполнения программы и возвращают Haxe код, который и будет выполнен на этапе исполнения программы. Neko дает доступ к файловой системе и вообще к системе в целом, а haxe.macro классы позволяют... Да они все позволяют: создавать новые классы, менять структуру существующих, получать полные данные о всех типах, enum-ах и т.д. в общем полный доступ. Главное знать, что именно вам надо. Все это и делает макросы такими интересными для нас. Но не будем сильно затягивать и посмотрим на пример, который будет запоминать в скомпилированном приложении и выводить дату сборки проекта (без сторонних утилит такую задачу решить довольно сложно и тут на помощь приходит макрос):

Код AS3:
import haxe.macro.Context;
import haxe.macro.Expr;
 
class Main {
 
	#if !macro
	static function main() {
		trace(getBuildDate()); // 2013-05-04 14:11:44
	}
	#end
 
	@:macro static public function getBuildDate():Expr {
		var d = Date.now();
		return Context.makeExpr(d.toString(), Context.currentPos());
	}
}
Функция getBuildDate и есть наш макрос. Сразу обращаем внимание на мета тег @:macro в начале функции - это отличительный знак, говорящий компилятору, что выполнять эту функцию надо во время компиляции! Наша функция возвращает тип Expr, о нем немного позже. Дальше в методе getBuildDate создается обычный Date с текущей датой, который переводится в строку и передается в “магический” Context.makeExpr и еще менее понятный метод Context.currentPos. И тут стоит вернуться к типу Expr, его определение легко найти в коде модуля haxe.macro.Expr

Код AS3:
typedef Expr = {
	var expr : ExprDef;
	var pos : Position;
}
Expr - это просто структура с двумя полями: expr - любое выражение, допустимое в Haxe, но не в привычном виде, а как одно из значений ExprDef enum-а (перечисляемого типа), например EFunction, EVar, ENew, EConst, ECall, EContinue, EReturn и т.д. И pos - указатель на место, где в файле будет расположено выражение. На самом деле pos самому вычислять придется не так часто и для начала запомним, что на его место подставляем Context.currentPos(). Вот как выглядит Position тип:

Код AS3:
typedef Position = {
	var file : String;
	var min : Int;
	var max : Int;
}
Теперь, когда Expr перестал быть полной загадкой, вернемся к методу Context.makeExpr. Из названия понятно, что он что-то делает и вот тут лучше, как говорится, один раз увидеть, что-же он делает:

Код AS3:
trace(Context.makeExpr(d.toString(), Context.currentPos()));
// { expr => EConst(CString(2013-05-04 14:11:44)), pos => #pos(src/Main.hx:8: characters 8-20) }
Вернитесь к описанию структуры Expr и убедитесь, что перед нами действительно Expr, содержащий одну строковую константу Econst(CString()) с датой сборки проекта и расположенную в Main.hx на 8 строке, и занимающую 8-20 символы, и это очень важно! Взгляните на 8-ю строку первого примера с макросом, там написано:

Код AS3:
trace(getBuildDate());
8-й символ - как раз начало getBuildDate строки (“trace(“ + 2 символа табуляции в начале строки), а 20-й - ее окончание. Т.о. вызов макроса заменится на выражение со строковой константой “2013-05-04 14:11:44”. Если вы упустили этот волнительный момент, я повторюсь: Мы только что заменили вызов метода на строку с текущей датой, и эта замена выполнена во время компиляции один раз!

Если запустить теперь приложение, мы увидим Main.hx:8: 2013-05-04 14:11:44. И сколько бы раз мы не запускали приложение, дата на экране не будет меняться, т.к. она была записана на этапе компиляции.

Вот и свершилось: вы разобрали и, надеюсь, поняли свой, возможно, первый, но далеко не последний макрос. Хотя уверен, что остался вопрос: “Что за магические #if !macro перед main функцией?”. Все дело в том, что macro функции сильно влияют на поведение класса, в котором они определены, да и импорты, доступные макро функциям, часто непозволительны остальному коду, вот и пришлось так извиваться, чтобы уместить все в один модуль. Но мой вам совет (да и вообще так правильнее): пишите макросы в отдельно отведенных для этого классах, не смешивая их с остальным кодом. Дальше я буду делать только так, но “смешанный” вариант я не мог не показать.

Признаюсь, в этой статье я хотел написать еще кучу всяких макросов, чтобы завлечь как можно больше людей, но понял, что ваши знания очень малы, и делать что-то крутое слишком рано. А вот усложнить наш первый макрос - самое время!

Усложним задачу. Использовать строку с датой хорошо, и ее можно распарсить в привычный Date, ну так давайте и сразу вызывать парсинг строки, т.е. чтобы getBuildDate() заменялся на Date.fromString(“2013-05-04 14:11:44”); Обратите внимание, что макро функции могут вернуть целое выражение.

Задачу мы себе поставили не самую простую, а даже немного сложную. makeExpr нам уже не поможет, он умеет работать только с базовыми и перечисляемыми типами (Int, Float, String, Bool, Array и анонимные объекты, составленные из этих типов), самое время обратиться к Context.parse методу. Смотрим, что у меня получилось:

Код AS3:
@:macro static public function getBuildDate2():Expr {
	var d = Date.now();
	return Context.parse("Date.fromString('" + d.toString() + "')", Context.currentPos());
}
Видно, что Context.parse первым параметром принял строку, содержащую Haxe код, а вот на ее результат советую взглянуть самим, лишь подскажу, как я это сделал:

Код AS3:
var date = getBuildDate2();
trace(date);
trace(Type.typeof(date));
Context.parse - очень полезный метод для парсинга строк, содержащих Haxe код, например, из внешнего файла или самостоятельно собранных строк, как на примере выше. Еще есть одна хитрая задачка, которую можно решить только с помощью этого метода, и о ней я как нибудь расскажу. Но, по правде сказать, я недолюбливаю parse и стараюсь использовать его только при крайней необходимости, хотя бы потому, что передаваемые строки могут содержать синтаксические или логические ошибки, да и лишний парсинг отнимает время. Дальше я покажу, как в нашей задаче можно обойтись без parse.

Чтобы “избавиться” от Context.parse, да и для того, чтобы показать силу макросов, напишем все то же, но иначе и сложнее . Но для начала вернемся к структуре ExprDef, как я говорил, она описывает любое выражение в Haxe, а значит сможет описать и наш Date.fromString(). “Но как это сделать,” - спросите вы, и я вам признаюсь честно, я не знаю. Нет, ну я догадываюсь, некоторые ExpDef я знаю, а остальное можно найти в документации, но я покажу вам максимально простой метод узнать как записать нужное вам выражение. Все очень просто, создадим вот такой метод:

Код AS3:
@:macro static function test(e:Expr) {
	trace(e);
	return e;
}
и вызовем, передав ему нужное нам выражение:

Код AS3:
trace(test(Date.fromString("2013-01-01")));
 
//src/Main.hx:16: { expr => ECall({ expr => EField({ expr => EConst(CIdent(Date)), pos => #pos(src/Main.hx:8: characters 13-17) },fromString), pos => #pos(src/Main.hx:8: characters 13-28) },[{ expr => EConst(CString(2013-01-01)), pos => #pos(src/Main.hx:8: characters 29-41) }]), pos => #pos(src/Main.hx:8: characters 13-42) }
Перед вами ни что иное, как запись haxe кода с помощью Expr. Если немного укоротить полученную строку, то выйдет нечто:
Код AS3:
ECall(EField(Date, “fromString”), [2013-01-01”])
Т.е. мы находим поле (метод) fromString у класса Date и вызываем его, передав в качестве параметра массив, содержащий одну строку с текущей датой. Предлагаю сдержать крики “О боже, как все сложно!” и просто взглянуть на метод, который в итоге получился:

Код AS3:
@:macro static public function getBuildDate3():Expr {
	var d = Date.now();
	var p = Context.currentPos();
	return { expr:ECall(
			{ expr:EField(
				{ expr:EConst(CIdent("Date")), pos:p },
				"fromString"),
			pos:p },
			[ { expr:EConst(CString(d.toString())), pos:p } ]),
		pos:p };
}
Ну, я же говорил ,что сделаем сложнее, вот мы и сделали. Я не стану вас убеждать, что так правильнее или еще что-то, я лишь скажу, что дальше будет еще один вариант, намного проще этого и если вам пока не охота разбираться, что тут и как, сразу переходите дальше, но не забывайте, что с Expr и ExprDef вам все равно придется работать, когда вы дойдете до сложных макросов и обычные parse и makeExpr вам там уже не помогут. Главное, не бояться почаще смотреть, как сам Haxe собирает выражения (метод test выше), и все у вас получится. И не поленитесь внимательно изучить всю строку с ретурном хотя-бы на этом простом примере.

Но и это еще не все! Последний вариант хоть и работает, но заслуженно вызывает испуг у большинства. И хотя Николас (автор языка Haxe) может думать как компилятор и даже вместо него и может заставить разработчиков делать также, однако, быстро стало ясно, что работу с макросами нужно как-то упростить. Результатом данного упрощения стало macro reification, которое упростило синтаксис и работу с макросами.

Вспомните, с чего мы начали: у нас есть строка с датой, и мы хотим передать ее в метод, который распарсит ее и вернет дату. Т.е. в идеале хотелось бы взять и написать return Date.fromString(d.toString()); и мы так и сделаем, или почти так:

Код AS3:
@:macro static public function getBuildDate4():Expr {
	var d = Date.now();
	var e = Context.makeExpr(d.toString(), Context.currentPos());
	return macro Date.fromString($e);
}
По-моему, получилось отлично! Результат getBuildDate4 совпадает с getBuildDate3, а внешне getBuildDate4 явно выглядят лучше. Взгляните на значение переменной е. Это именно то, что возвращал наш первый метод getBuildDate - выражение, содержащее строку с датой. Вся магия в последней строке после оператора return. Сначала мы видим оператор macro, который говорит компилятору, что все, что идет дальше, надо переводить сразу в Expr. Т.е. если написать
Код AS3:
macro “foo”
то это то же самое, что написать
Код AS3:
{expr:EConst(CString(“foo”)), pos:Context.currentPos()}
Согласитесь, отлично придумано. А чтобы в это выражение встраивать дополнительные значения извне, нужно передавать их с ключом $ вначале, тогда компилятор на это место подставит выражение из переменной, главное, чтобы она (переменная) тоже было типа Expr, в нашем примере это $e, переданная методу fromString. Т.о. весь ужас из нескольких вложеных enum-ов, мы записали все одной строкой: macro Date.fromString($e);, А в Haxe 3 это можно записать еще проще.

У Николаса в блоге есть очень наглядный пример того, как macro reification упростил код макросов, и я не могу его не показать:

Код AS3:
@:macro static function repeat( e : Expr, eN : Expr ) {
    return macro for( x in 0...$eN ) $e;
}
До упрощения этот макрос можно было бы записать минимум семью строками кода! Разбор того, что он делает и как работает оставляю на вас, надеюсь, теперь это не составит особого труда. Подсказка и вариант до упрощения тут.

Для первого раза, думаю, достаточно и предлагаю на этом остановиться. Подводя итоги, могу сказать, что теперь вы научились писать простейшие макросы, работать с Expr, узнали несколько полезных методов Context класса, а их на самом деле намного больше, немного познакомились с macro reification и т.д. Что вы не узнали, так это, как создавать свои классы и enum-ы, как редактировать целые классы, дополняя их методами или изменяя существующие и многое другое. Надеюсь, мне хватит сил и я обязательно обо всем этом напишу.

Напоследок, к разбору макроса из блога Николаса, предложу еще попробовать всем написать макрос, который будет сохранять значение файла в строку и работающий как показано ниже:
Код AS3:
var str:String = MyMacros.getFileContent(“readme.txt”);
Цитата:
Отдельная благодарность Александру Кузьменко, Александру Хохлову и SlavaRa за помощью в написании статьи, рецензирование, редактирование и полезную критику.
Всего комментариев 27

Комментарии

Старый 06.05.2013 15:57 carrotoff вне форума
carrotoff
 
Аватар для carrotoff
Это очень интересно!
Старый 06.05.2013 16:52 Котяра вне форума
Котяра
 
Аватар для Котяра
Немного о назначении макросов бы...
Т.е. зачем понадобилось записать дату?
Я-то это понимаю (например, просто для вывода в меню даты компиляции)
Но хотелось бы более интересный и нужный пример.
Старый 06.05.2013 17:00 Dima_DPE вне форума
Dima_DPE
Цитата:
Но хотелось бы более интересный и нужный пример.
Все так, но все более интересные и нужные примеры не вписываются в первую статью своей сложностью.

А дата сборки нужна, чтобы отчитываться перед заказчиком или просто самому знать когда ты это накодил. Во флеше видел мега пример решения этой задачи: флешка сама себя грузила считывая пару первых байт и брала от туда инфу о дате создания флешки. FlashDevelop специально делает доп параметр с датой компиляции, чтобы его можно было использовать внутри флеш проекта и т.д.

Главная задача этого примера не вставить дату сборки в код, а показать, что макрос может менять код на лету во время компиляции (саморедактируемый код).

Дальше постараюсь написать больше интересных примеров, готов даже выслушать пожелания.

Цитата:
Это очень интересно!
Спасибо, банальность, но фидбек даже такой очень важен, особенно для такого как я - начинающего автора.
Старый 06.05.2013 17:34 carrotoff вне форума
carrotoff
 
Аватар для carrotoff
Цитата:
Спасибо, банальность, но фидбек даже такой очень важен
Никакой банальности. Действительно интересно. Если в следующей статье (а я надеюсь, что вводная статья не окажется последней), покажете более интересный пример, что называется, для боевых условий, будет вообще шикарно.
Старый 06.05.2013 17:48 Dima_DPE вне форума
Dima_DPE
Цитата:
Никакой банальности.
Банальностью я назвал свои слова (читай "скажу банальность"). А по поводу новых статей, так идеи есть, есть люди, которые помогают, а так писать намного веселее.

Да и любые боевые задачи готов выслушать и по возможности осветить. На рассмотрении сейчас генерации классов/енумов, автоимпторт ассетов из папки во флеш проект, редактирование существующих классов (тут могу рассказать про перегрузку операторов реализованную мной раньше или придумать что то новенькое, например встраивание в класс базовой реализации интерфейсов). Жду идей.
Старый 06.05.2013 20:24 Котяра вне форума
Котяра
 
Аватар для Котяра
Вот задача, которую много кто решал разными способами:
1. есть файл version.xml или файл changelog
2. нужно вкомпилить его в константу Version.NUMBER

Это нужно для проверки клиента на необходимость обновления. Т.е. приложение сверяет свою версию с версией на сервере (чаще всего - тот же version.xml).
Пример очень схож с датой и, можно даже дату использовать в качестве номера версии, особенно если это просто таймстамп.

В as3 я решал это через ant - читал нужный файлик и передавал значение в качестве аргументов компиляции типа VERSION::number $version

Это простенький пример, но более жизненный)
Старый 06.05.2013 20:33 Dima_DPE вне форума
Dima_DPE
Цитата:
В as3 я решал это через ant
ну, вот отличная задача, которую в Haxe можно решить самим Haxe, не прибегая к стороним тулам. Примерно так:

Код AS3:
@:macro static public function getVersion():Expr {
	var f = sys.io.File.getContent("version.txt"); // changelog
	var version = Std.parseFloat(f);  // parse file content
	return Context.makeExpr(version, Context.currentPos());
}
При этом это решение будет работать и для клиента flash, js и для сервера php, neko и т.д.
Старый 06.05.2013 21:03 Котяра вне форума
Котяра
 
Аватар для Котяра
Усложняем задачу.
Мы читаем тот же version.txt и инкрементируем значение (пусть там будет Int)
Что в результате получаем: автоизменение номера версии не только в коде, но и в файле version.txt
Это замечательно.
Старый 06.05.2013 21:17 Котяра вне форума
Котяра
 
Аватар для Котяра
А вообще вот такая задача, которую я решаю посредством запуска разных таргетов анта (maven, ivy):
1. скачивание зависимостей
2. настройка путей компиляции (различные src для разных платформ)
3. настройка путей и имён выходных файлов
4. пакетная сборка всего этого.

Решаемо ли это именно макросами?
Или всё-таки это немного не то?
Насколько оправдано внедрение в "чистый" код параметров сборки?
Или лучше всё-же воспользоваться сторонними тулзами?
Как макросы могут взаимодействовать со сторонними тулзами? (теми же ant, gradle, maven, ivy)
Можно ли на haxe написать аналоги?
Старый 06.05.2013 23:23 Dima_DPE вне форума
Dima_DPE
Ну сборка это не совсем то, сборка это сборка, ант никто не отменял. мавен плагин для хакса тоже есть, valyard пилит на гитхабе. Макрос может считать параметры сборки и в зависимости от них вести себя по разному, может чтото скачать, вызвать сторонее приложение, но собирать чтото макросами я бы не стал.
Старый 07.05.2013 00:59 Котяра вне форума
Котяра
 
Аватар для Котяра
Я тогда просто не вижу, что ещё кроме даты и версии могло бы быть полезным.
Загрузка какого-то конфига через макросы и в соответствии с ним генерация каких-либо констант и/или даже классов и функций?
Чем это лучше условной компиляции в ас3?
Или просто прописыванием других путей для патчинга при сборке. (кстати патчинг - это прикольная фишка - правда нарушает все ООп принципы и я уже запарился копипастить))
Я не придираюсь. Мне реально интересно.
Старый 07.05.2013 01:03 Котяра вне форума
Котяра
 
Аватар для Котяра
Можешь просто без кода написать прикольные штуки которые может делать макрос.
Типа:
* Макросом можно спросить у компа его макадрес - вшить его в константу.
* Макросом можно вызвать чакнориса и убить диавола, если макадрес 666.
* Макросом можно вызвать разрыв мозга
итп
Старый 07.05.2013 02:52 Dima_DPE вне форума
Dima_DPE
Цитата:
Макросом можно вызвать разрыв мозга
Это максимально близко к истине.
Старый 07.05.2013 03:11 Dima_DPE вне форума
Dima_DPE
Котяра, начни со статьи на википедии http://ru.wikipedia.org/wiki/%D0%9C%...BD%D0%B8%D0%B5 . Когда будет понятно зачем метопрограммирование, вопросы зачем нужны макросы отпадут.
Старый 07.05.2013 08:26 СлаваRa вне форума
СлаваRa
 
Аватар для СлаваRa
Например, я вот, не люблю когда кода много.
Не так часто, но мне приходится работать с Singleton'ами, возможно ли с помощью макросов кода вида:
Код AS3:
class SomeSingleton {
 
	public static var instance(get_instance, null):SomeSingleton;
 
	static function get_instance():WorldClock {
		if (instance == null) {
			instance = new SomeSingleton();
		}
		return instance;
	}
 
	function new() {
		initialize();
	}
 
	function initialize() {
 
	}
 
}
получить что-то вроде
Код AS3:
class SomeSingleton {
 
	public static var instance(default, null):SomeSingleton;
 
	function initialize() {
 
	}
 
}

Очень частая задача это работа с конфигами, например описание игровой карты
Код:
{
	"name" : "map",
	"levels" : ["@level/level_1", "@level/level_2"]//список ссылок на конфиги уровней
}

{
	"name" : "The first level",//имя уровня
	"asset" : "@assets/swf/levels/level_1.swf"//url ассета содержащего уровни(загружается в рантайме)
}
Обычно при старте приложения, загружаются конфиги, и в каком-то утилитном классе происходит их парсинг и заполнение какой-то модели данных, учитывая, что эти данные статичны, т.е. они не могут измениться в рантайме, можно было бы производить парсинг и создание подели данных в момент сборки. Возможно ли это сделать с помощью макросов

Так же это может быть полезно при конфигурации GUI, например с помощью XML или JSON


Возможно ли при помощи макросов создавать DSL или что-то подобное?
Старый 07.05.2013 09:08 alexcon314 вне форума
alexcon314
Цитата:
Главные плюсы макросов - это то, что в них, кроме стандартной библиотеки, доступны еще и все классы пакетов neko и haxe.macro и то, что функции-макросы вызываются на этапе компиляции, а не во время выполнения программы и возвращают Haxe код, который и будет выполнен на этапе исполнения программы. Neko дает доступ к файловой системе и вообще к системе в целом, а haxe.macro классы позволяют... Да они все позволяют: создавать новые классы, менять структуру существующих, получать полные данные о всех типах, enum-ах и т.д. в общем полный доступ.
Меня сбивает с толку ваша ссылка на статью о метапрграммировании и ваше толкование макросов. Ибо макрос в исконном виде - не более, чем макрокоманда, последовательность действий, упакованая для упрощения чтения и краткости в некий дескриптор, условно говоря. При компиляции декскриптор просто разворачивается в точную последовательность тех самых действий. Это очень удобный инструмент в деле. Я не упускаю случая им воспользоваться каждый раз, когда программирую на С, к примеру. Но при чем тут метапрограммирование? Ну, шаблонизация кода, да, что еще? Из вашей статьи я не понял как работают макросы и макросы ли это вообще, я не понимаю половины слов в приведенной цитате.
Возможно, макросы в хаксе - это такой бэкдор в "классы пакетов neko и haxe.macro"? Т.е. в рантайме они не доступны? Что же полезного в таком "макросе" и что за "Haxe код" они возвращают?
Другим краем сознания я понимаю, что автор всего этого хозяйства, конечно, хотел как лучше и, видимо, он заслуживает респекта. Ну, и конечно, хочется посмотреть на продолжение статьи, возможно, там все прояснится.
Цитата:
Макросы в Haxe используют неоправданно мало программистов, кого-то отпугивает их синтаксис, кто-то просто не знает, что это и зачем.
Вообще, большинство программистов знают, что такое макрос и никого никогда не отпугивал их синтаксис. Макросы в хаксе - что-то особенное? Или таки надо зарываться в глубь и вширь, уходя от "плоского" понимания термина "макрос", чтобы постигнуть?
Цитата:
Такие вещи, как генерация классов или enum-ов или редактирование существующего кода, я не затрону, лишь замечу, что все это возможно в пределах Haxe макросов!
Я, наверно, старомоден, меня это пугает.
Обновил(-а) alexcon314 07.05.2013 в 09:28
Старый 07.05.2013 09:26 СлаваRa вне форума
СлаваRa
 
Аватар для СлаваRa
Я думаю, что для рядового ActionScript программиста, или HaXe программиста, который вырос из первого, макросы это действительно мир непонятный.
Для HaXe очень мало информации по ним, очень мало примеров, и не всегда понятно где и зачем их использовать.

@alexcon314 а чем ссылка не в тему?
Старый 07.05.2013 09:30 alexcon314 вне форума
alexcon314
Ну, не то что не в тему, я как-то ожидал, что немного с другого начнут.
Старый 07.05.2013 09:32 СлаваRa вне форума
СлаваRa
 
Аватар для СлаваRa
а все, теперь я, наверное, понял о чем речь
Старый 07.05.2013 11:29 RealyUniqueName вне форума
RealyUniqueName
@СлаваRa
Singleton: можно, и даже более того: https://github.com/imps/singleton
Конфиги парсить, "вшивать" можно. Для модели есть даже набор макросов в стандартной библиотеке haxe - SPOD, который по структуре базы данных генерирует классы модели.

Для гуя и шаблонизаторов можно использовать макросы, чтобы делать всё type-safe и исключить время, затрачиваемое на парсинг шаблонов/xml во время выполнения программы.
Например, вот либа, которая по разметке xml генерит haxe код: https://github.com/RealyUniqueName/StablexUI
Макросы позволяют отлавливать ошибки в шаблонах/xml на этапе компиляции и встраивать haxe код прямо в шаблоны, что даёт невероятную гибкость:
Код AS3:
<!-- компиляция не пройдёт и выдаст ошибку, что alpha должен быть Float, а не String -->
<Sprite alpha="wtf_this_should_be_float" />
 
<!-- можем встраивать произвольный haxe код в атрибуты вместо скучных значений -->
<Sprite width="MainClass.SOME_CONST * 2 + Std.random(100)" />
С DSL не разбирался, но если я правильно понимаю, то собственный язык шейдеров в haxe попадает под это определение: HXSL - http://haxe.org/manual/hxsl
Обновил(-а) RealyUniqueName 07.05.2013 в 13:55
Старый 07.05.2013 11:39 RealyUniqueName вне форума
RealyUniqueName
@alexcon314
Да, в C макрос - это просто макро команда. В Haxe - это гораздо больше (см мой предыдущий комментарий).

Не пугайтесь генерации/модификации классов )
Посмотрите тот же пример с синглтоном: https://github.com/imps/singleton
Или генерацию классов модели: http://haxe.org/manual/spod

Ещё есть интересный пример:
В Haxe нет классических абстрактных классов (есть абстрактные типы данных, но это другое), но с помощью простого макроса в 20 строк кода можно реализовать эту конструкцию языка.
Обновил(-а) RealyUniqueName 07.05.2013 в 15:01
Старый 07.05.2013 12:38 СлаваRa вне форума
СлаваRa
 
Аватар для СлаваRa
вот еще бы тему комплишенов для генерации и вшивания кода, развернуть было бы здорово
Старый 07.05.2013 12:45 Dima_DPE вне форума
Dima_DPE
А что там раскрывать Haxe сам все делает. Если вернутся к коду:
Код AS3:
var date = getBuildDate2();
то напиши date. (дейт с точкой) то дальше haxe выведет все допустимые для Date методы и свойства в комплетишион, а все потому что, Haxe по сути выполнит проект и разберет тип переменной date, даже если ее значение вернет макрос. Правда, чем больше макросов, тем дольше он будет пересобирать проект, но с появлением инкрементной сборки все стало в разы быстрее.
Старый 07.05.2013 12:51 СлаваRa вне форума
СлаваRa
 
Аватар для СлаваRa
ну вот как-то упоминалось о комплишенах для внешних XML\JSON, только ссылку так найти и не получилось
Старый 07.05.2013 12:58 alexcon314 вне форума
alexcon314
Должен признать, да, в хаксе это гораздо больше. Пример с синглтоном вполне убедил).
Старый 07.05.2013 13:14 RealyUniqueName вне форума
RealyUniqueName
@Котяра
1. Мне пока не приходилось работать с мак адресами, но вот что с ходу пришло в голову:
- с помощью класса sys.io.Process запускаем команду ifconfig (это для линукса. Для винды хз, где смотреть мак)
- вытаскиваем из вывода команды мак адрес
- если сделаем это в макро-функции, сможем сохранить мак разработчика в коде.
2 и 3. http://haxememes.tumblr.com/post/42315290417

@СлаваRa
К сожалению, так и не смог найти этот пример с автодополнением по json/xml, но точно помню, что где-то видел его. Самому мне сейчас в голову не приходит хорошее решение этой задачи. Будет время, подумаю )
Старый 07.05.2013 13:41 Dima_DPE вне форума
Dima_DPE
Цитата:
(это для линукса. Для винды хз, где смотреть мак)
ipconfig /all

Цитата:
К сожалению, так и не смог найти этот пример с автодополнением по json/xml...
Ну вот еще одна отличная тема для статьи.
 

 


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


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