Язык haXe
10 августа 2008
Доклад для 1-й конференции BAFPUG
- Что такое haXe
- Подробнее о языке
- Преимущества haXe
- Недостатки haXe
- Фишки haXe
- Возможности по оптимизации производительности
- Примеры проектов на haXe
Что такое haXe
haXe это:
- технология разработки веб- и десктоп-приложений;
- технология разработки флэш-приложений;
- язык программирования, компилятор и фреймворк классов;
Основная идея haXe состоит в том, что исходный код на одном языке программирования компилируется (или транслируется) на разные платформы:
- swf-файл (9-й или более ранних версий);
- Neko байт-код;
- JavaScript-код;
- PHP-код;
- ActionScript3-код;
И таким образом все части веб-приложения (клиентская часть и серверная логика) разрабатываются на одном языке. Клиентская часть может быть реализована средствами Flash, JavaScript, HTML, серверная логика средствами Neko или PHP. Это уникальная идея. Насколько мне известно, кроме haXe, больше ничего подобного нет.
Основная идея haXe состоит в том, что разработчику не нужно знать PHP, MySQL, HTML, CSS, JavaScript, Flash и прочие технологии, а нужно знать только один язык -- haXe, и этот язык делает все, что обычно делается вышеуказанным набором технологий.
По замыслу Николаса Каннассье, автора haXe, это должно уменьшить порог вхождения в веб-разработку, облегчить взаимопонимание и сотрудничество в команде, где разные участники работают над разными частями веб-проекта, сделать возможным взаимозаменяемость разработчиков проекта.
В контексте haXe мультиплатформенность понимается как способность компилятора генерировать байт-код или скрипты для разных технологий (целевых платформ в терминологии haXe). В тоже время haXe является мультиплатформенным и в обычном смысле -- компилятор и средства разработки доступны в Windows, Mac OS и Linux.
Все эти целевые платформы широко известны, кроме Neko. Поэтому о нем нужно сказать отдельно. Neko -- это еще одна виртуальная машина и еще один язык программирования, также созданные Николасом Каннассье. Язык несколько особенный, ибо изначально создавался с расчетом, что код будет динамически генерироваться из haXe, а не писаться вручную программистом.
Neko обеспечивает все то, что недоступно для Flash и JavaScript -- работу с файловой системой, доступ к базам данных, работу с сетью, архивацию и прочее. На нем реализуется серверная логика и на нем можно создавать десктопные приложения. Виртуальная машина Neko может сама работать как веб-сервер или может подключаться как модуль Apache. Чтобы запустить свой проект на haXe, нужен выделенный сервер, потому что вряд ли реально найти хостинг, поддерживающий Neko. Мне кажется именно это и было главной причиной, ограничивающей широкое распространение haXe.
Николас тоже это понял, и последняя версия haXe2.0, вышедшая совсем недавно (официальный релиз был 29 июля, хотя бета-версия в исходных кодах была доступна раньше), поддерживает трансляцию в PHP-код. А вот это уже реальный шанс для haXe получить широкую известность.
Подробнее о языке
haXe -- язык программирования, подразумевающий главным образом ООП парадигму. Хотя на нем можно программировать также в процедурном и функциональном стиле.
Если говорить об ООП, то в основном используется подход, основанный на классах и строгой типизации, очень похожий на Java. В то же время haXe имеет возможности более классического и более гибкого ООП, основанного на прототипах и динамической типизации, похожего на SmallTalk. Второй вариант возможен за счет типа Dynamic (аналогичный типу Object в ActionScript).
Функциональный подход обеспечивается за счет поддержки локальных функций, передачи функций в виде аргументов другим функциям с формированием сложных многозвенных рекурсий. Впрочем, это для крутых хакеров. В haXe любой блок кода возвращает какое-то значение, что тоже характерно для функциональных языков программирования.
При разработке языка ставилась задача найти компромисс между надежностью, которую дает строгая типизация, и гибкостью, которую дает типизация динамическая. И компромисс найден удачный.
В принципе, все тоже самое характерно и для ActionScript, но haXe все-таки гибче и богаче по возможностям, имеет свои интересные фишки, о которых будет рассказано ниже.
haXe поставляется с обширным базовым набором библиотек. Различают мультиплатформенные библиотеки и библиотеки специфичные для конкретной платформы -- Flash, JavaScript, Neko.
Мультиплатформенные библиотеки одинаково работают на всех целевых платформах. Они обеспечивают работу со строками, датами, математические функции, парсинг XML, поддержку регулярных выражений.
Flash-библиотеки в полном объеме дублируют API флэш-плеера 9-й версии (10-я версия пока не поддерживается).
JavaScript-библиотеки обеспечивают доступ к DOM-модели документа, обработку событий, работу с историей браузера и такую важную вещь, как XmlHttpRequest -- сердце технологии AJAX. Сгенерированый JavaScript код является кроссбраузерным и основан на собственном фреймворке.
Neko-библиотеки обеспечивают серверную логику, доступ к файловой системе, работу с базами данных.
haXe имеет Remoting-фреймворк для обеспечения взаимодействия между swf-файлом, JavaScript-кодом и серверной частью.
Ну и нужно еще упомянуть особенность XML-парсера. Из соображений кросс-платформенности он реализован с нуля, на базе регулярных выражений. Из-за этого он работает существенно медленнее, чем парсер флэш-плеера. На XML-файлах большого размера это может быть заметно. При разработке флэш-клиента, вместо универсального парсера можно использовать парсер флэш-плеера, который тоже, конечно, доступен.
Преимущества haXe
- Замысел — один язык — много платформ;
- API флэш-плеера доступно в полном объеме;
- Можно использовать Flex-фреймворк;
- Значительное количество библиотек;
- Язык более гибкий и лаконичный, с дополнительными возможностями оптимизации;
- Быстрый компилятор (заметно быстрее, чем mxmlc);
- Активное сообщество (англоязычное);
- Полная (но лаконичная) документация;
- Быстро обновляется в след изменениям флэш-плеера;
- Возможность создания мультиплатформенных классов и библиотек;
- Снижает порог входа в веб-разработку;
- Дает возможность делать веб-приложения и флэш-приложения пользуясь исключительно open source инструментами;
Замысел — один язык — много платформ
Ценность этого подхода в том, что команда разработчиков использует один язык для разработки всех частей системы: клиентской-флэш части, клиентской JavaScript части, серверной части. По идее, это должно улучшать взаимопонимание и взаимодействие членов команды. Так позиционирует язык сам Николас, но я не очень в это верю. Разработка клиентской и серверной части отличается не только синтаксисом языков программирования. Слишком велика разница в прикладных областях и средах, в которых функционируют программы. Так что синтаксис тут дело десятое. Но раз уж это главная идея haXe, то ее я и поставил на первое место в списке достоинств.
API флэш-плеера доступно в полном объеме
То, что API флэш-плеера полностью доступно — очень важный момент. Это значит, что разница между haXe и Flex-AS3-MXML есть только в процессе разработки. А результаты разработки — swf-файлы, одинаковые. И все, что можно сделать на Flex, можно сделать и на haXe. Вот это для меня и есть главное достоинство haXe.
Можно использовать Flex-фреймворк
Flex-фреймворк и mx-классы подключаются не совсем простым способом. То, что они вообще подключаются, это достоинство. Но то, как они подключаются, это недостаток. Вообще же, разработка на haXe не подразумевает использование Flex-фреймворка. Вместо него существует большое количество собственных библиотек. Думаю, Flex-программистам, использующим PureMVC, будет интересно узнать, что этот фреймворк уже портирован на haXe.
Значительное количество библиотек
В разделе libs.haxe.org можно увидеть более 70 различный библиотек кода для haXe. Среди них имеются библиотеки gui-компонентов: arctic и fcomponentshx, библиотеки для поддержки AIR и компонентов Flex, 3D-движки и движки для игр, движки для анимационных эффектов, фреймворки для веб-приложений, библиотеки для создания десктоп приложений (в Windows и в Linux). В общем, там много всего -- весь список я не осилил просмотреть.
Не лишне будет заменить, что с haXe можно использовать gui-библиотеку AsWing, на haXe портирован известный фреймворк PureMVC и haXe имеет собственный медиа-сервер -- haxeVideo, поддерживающий публикацию потокового видео и запись FLV-файлов.
Язык более гибкий и лаконичный, с дополнительными возможностями оптимизации
О фишках haXe и об возможностях оптимизации ниже будут отдельные разделы.
Быстрый компилятор (заметно быстрее, чем mxmlc)
mxmlc компилирует достаточно быстро, но он тратит время на парсинг своего конфига, который представляет собой довольно большой XML файл. И он делает это при каждом запуске. Чисто субъективно, компилятор haXe на моем проекте, состоящем из 20 классов срабатывает мгновенно, а mxmlc в составе Flex Builder 3 alpha на проекте из 2-х классов срабатывает с заметной задержкой в 2-3 секунды. Я часто компилирую код и для меня такая разница существенна.
Активное сообщество (англоязычное)
Сообщество haXe действительно активно. В списке рассылки много обсуждений, в которых часто участвует сам Николас. Там охотно помогают новичкам, отвечая даже на дурацкие вопросы.
Полная (но лаконичная) документация
Документация по haXe существует в форме wiki (как и весь сайт haxe.org). Она полная — описаны все классы, как специфичные для разных платформ (Flash8, Flash9, JavaScript, Neko), так и универсальные. И есть много материалов, типа "быстрый старт", помогающим новичкам начать работу с haXe. Документация переводится энтузиастами на многие языки.
Быстро обновляется в след изменениям флэш-плеера
Ну что говорить, API 9-го флеш-плеера поддерживается в полном объеме, работа над API 10-го флеш-плеера идет.
Возможность создания мультиплатформенных классов и библиотек
Я уже упоминал мультиплатформенные классы, входящие в стандартную поставку haXe. Ничто не мешает писать и свои такие же классы. Не так уж редко возникает необходимость иметь одну и ту же логику и в клиентской и в серверной части. Например, мне приходилось делать он-лайновые игры -- шахматы, шашки, нарды. И значительная часть логики дублировалась в клиенте и на сервере. Клиенту нужно вычислять допустимые ходы для данной фигуры, чтобы показать игроку возможные варианты. Серверу тоже нужно это делать, чтобы убедиться, что пользователь сделал корректный ход. Соответствующую логику я сначала писал на ActionScript, потом переносил на РНР. haXe позволяет написать такую логику один раз, а затем скомпилировать ее дважды под разные платформы.
Снижает порог входа в веб-разработку
В свое время такую роль сыграл РНР -- значительно упростил веб-разработку, снизил порог входа в программирование и очень многих сделал программистами. Теперь тоже самое может сделать haXe. Собственно, это одна из целей создания haXe.
Дает возможность делать веб-приложения и флэш-приложения пользуясь исключительно open source инструментами
Флэш-платформа долгое время была закрытой, и только недавно начала открываться. Между тем, open source флэш-разработчики существуют уже давно (они обитают на сайте osflash.org). Существует значительное количество разработчиков с принципиальной позицией в отношении закрытых технологий. И для них haXe хороший, идеологически чистый вариант. Не так давно и в Adobe поняли, что не худо бы привлечь побольше разработчиков на свою платформу, в том числе и open source разработчиков, и начали постепенно открывать свои технологии.
Недостатки haXe
У haXe никаких недостатков нет! Шутка :)
- Нет мощной IDE, сравнимой с Eclipse или Flex;
- Нет отладчика;
- Нет визуального gui-построителя;
- Отсутствует русскоязычное сообщество;
- В сравнении с документацией по Flex, AS3, документация haXe слишком скудная;
Нет мощной IDE, сравнимой с Eclipse или Flex
Нет отладчика
Ну конечно, этого так не оставят. Нормальная IDE скоро будет. Сразу в комплекте с отладчиком. Это будет Eclipse с плагином EHX. Вернее сказать, этот плагин есть уже и сейчас, только он пока мало на что годен. Долгое время проект казался мертвым. Но в мае разработчики появились в списке рассылки haXe и пообещали, что работа ведется, в скором времени плагин обновится, и там будет отладчик.
Нет визуального gui-построителя
Нет, и вероятнее всего в обозримом будущем не будет — этот вопрос как-то не заботит haXe-сообщество. Но и без него можно жить.
Впрочем, AsWing имеет gui-builder, а haXe может использовать AsWing. Так что если покопаться в этом направлении, то возможно что-то получится.
Отсутствует русскоязычное сообщество
Да, как такового, русскоязычного сообщества нет. Сайт haxe.ru имеет целью создать такое сообщество. Он существует уже больше года, но пока активность на сайте очень низкая. Но, между тем, русских разработчиков в haXe достаточно много. Русские имена есть и среди разработчиков comapping.com, библиотеки arctic и в других проектах, некоторые из них активны в списке рассылки haXe -- то есть, они часть англоязычного сообщества.
В сравнении с документацией по Flex, AS3, документация haXe слишком скудная
Документация достаточна для того, чтобы освоить эту технологию. На мой взгляд, в ней не хватает примеров кода, как это есть в документации по ActionScript. Что ж, кому, как не нам это исправлять. Будет опыт, будет и документация.
Фишки haXe
Есть прекрасное описание основ haXe на официальном сайте, и есть русский перевод, сделанный Юрием Кетовым, владельцем сайта haxe.ru. К этим материалам и нужно обращаться в первую очередь. Здесь я только кратко упомяну некоторые фишки.
функция trace
Она значительно мощнее в сравнении в функцией trace в ActionScript, что частично компенсирует отсутствие отладчика. Первая особенность -- функция выводит позицию в коде, откуда она была вызвана (полное имя класса, имя метода, номер строки). И это очень помогает в отладке. Вторая особенность -- ее можно заменить собственной функцией, где отформатировать вывод на свое усмотрение и направить его куда захочется. У меня эта функция оформляет сообщения разными цветами и через XMLSocket посылает их на специальный отладочный сервер, который выводит их в консоль. Подробнее об этом можно почитать на haxe.ru здесь и здесь.
Блоки возвращают значения
Любой блок -- участок кода, заключенный в фигурные скобки, возвращает значение определенного типа. Это значение последнего выражения в блоке. И это значение можно присвоить переменной, например так:
var a:Int = { var b = 10; var c = 20; b + c; }
trace(a); // output 30
var b:Int = if(a > 10) { a += 10; ++a; }
else { a -= 10; --a; }
trace(b); // output 41;
Типизированные массивы
Массивы могут быть типизированы, для чего используется следующий синтаксис:
var ar:Array<String> = new Array();
ar.push("Hello");
ar.push(5); // compile error
var ar2:Array<Int> = new Array();
ar2.push(1);
ar2.push(2);
ar2.push("3"); // compile error
это позволяет повысит производительность, потому что при доступе к элементу массива
его тип известен сразу, без явного приведения.
Цикл for
Цикла for в обычном виде нет, используются итераторы.
var a:Array<String> = ['a', 'b', 'c'];
for(i in 0...a.length)
{
trace(i + " " + a[i]);
}
for(item in someObj)
{
item.doSomething();
}
Первый пример -- типичный способ обхода массива. Второй пример подразумевает,
что someObj реализует интерфейс Iterator и имеет собственный метод для обхода
элементов.
Поддерживает исключения (кроссплатформенно)
Синтаксис здесь довольно стандартный - throw, try, catch. Каких либо отличий от других языков, поддерживающих исключения, я не заметил. При обработке исключений и выводе информации доступен стек вызовов функций от места где произошло исключение, до места, где оно было перехвачено.
Локальные функции
Как и в ActionScript, поддерживаются локальные функции. Их можно передавать в виде параметров другим функциям. Здесь есть забавный пример, как две функции передают себя друг другу и формируют сложную рекурсию (говорят, подобные фокусы типичны для функционального программирования, но я далек от него и мне не так просто понять, что там происходит).
Особенность haXe в том, что локальные (да и не локальные) функции типизированы как и переменные. Например функция
var Some = function(a:Int, b:String):Stringимеет тип Int->String->String. Это может использоваться так:
var Some = function(a:Int, b:String):String
{
return b + (++a);
}
var Other = function(f:Int->String->String):Void
{
trace(f(10, "res: ")); // output res: 11
}
Other(Some);
здесь функция a принимает в качестве параметра функцию типа Int->String->String и вызывает
ее в своем теле.
Функция, не принимающая параметров и ничего не возвращающая имеет тип Void->Void. Попробуйте догадаться, что значит тип Void->Void->Void. Если догадаетесь, можете считать себя настоящим haXe программистом.
Чем это может быть полезно? В некоторых ситуациях это может заменить интерфейсы. Хотя еще лучше для этого подходит typedef, о котором речь пойдет ниже. Это прекрасно подходит для обработчиков событий и делегатов.
public function AddChangeEventListener(Listener:Dynamic->Void):Void
{
this.tf.addEventListener(TextEvent.TEXT_INPUT, Listener);
this.tf.addEventListener(FocusEvent.FOCUS_OUT, Listener);
}
вот так можно добавить обработчики событий.
haxe.Log.trace = Debug.Trace;а вот так мы подменяем стандартную функцию trace на собственную. Делегат для этого не нужен, достаточно простого присваивания.
Выявление типов
В haXe не обязательно указывать тип переменной при ее объявлении. При первом присваивании значения будет определен его тип и этот тип будет присвоен переменной. Этот процесс называется выявлением типов.
var vasja:User = new User(); // код чуть длиннее, чем хотелось бы var petja = new User(); // так тоже можно, это лаконичнее var i; // i имеет тип Unknown i = 5; // i имеет тип Int i = 'some'; // ошибка компиляции
Интерфейсы описывают не только методы, но и свойства
interface IPoint
{
var x:Int;
var y:Int;
function Length():Int;
function Add(p:IPoint):Void;
}
иногда это бывает полезно.
typedef
typedef очень интересные и полезные штуки, заслуживающие отдельного разговора. Они могут заменить собой небольшие классы, частично заменить интерфейсы, и использоваться там, где нужен полиморфизм.
typedef Some = { var a:Int; var b:Int; var Do:Int->Int->Int; }
class Foo
{
public var a:Int;
public var b:Int;
public var Do:Int->Int->Int;
public function new(a:Int, b:Int)
{
this.a = a;
this.b = b;
this.Do = this.DoSomething;
}
public function DoSomething(c:Int, d:Int):Int
{
return this.a + this.b + c + d;
}
}
class Test
{
static public function main():Void
{
var Process = function(item:Some):Int
{
return item.Do(item.a, item.b);
}
var t = {a:5, b:6, Do:function(a:Int, b:Int):Int { return a - b; }}
trace(Process(t)); // output -1
var item = new Foo(10, 5);
trace(Process(item)); // output 30
}
}
Этот код демонстрирует как раз реализацию полиморфизма с помощью typedef. Полиморфизм работает внутри функции Process. Ее параметр типизирован как тип Some, определенный через typedef. Это значит, что любой объект, имеющий свойства с такими же именами и типами, может быть передан этой функции.
Сначала мы создаем объект t, соответствующий типу Some, и функция Process без проблем его принимает. Затем создаем экземпляр класса Foo, тоже соответствующий типу Some, и Process также принимает и его.
Один нюанс -- хотя typedef не может содержать определение функции, но может содержать ссылку на функцию определенного типа. Что и демонстрируется в данном примере. Чтобы класс Foo был принят как тип Some, в нем нужно определить свойство Do типа Int->Int->Int и в конструкторе класса этому свойству присвоить ссылку на метод класса. Если просто определить метод класса Do типа Int->Int->Int, то класс Foo не будет принят как тип Some.
Еще одно полезное свойство typedef -- возможность создавать синонимы для типов данных.
typedef Sp = flash.display.Sprite;
class Test
{
static public function main():Void
{
var s = new Sp();
s.graphics.beginFill(0xff0000, 0.5);
s.graphics.drawRect(0,0,100,100);
s.x = 10;
s.y = 10;
flash.Lib.current.addChild(s);
}
}
Здесь мы определили синоним для класса Sprite и инстанциировали его через этот синоним. Это дает некоторую лаконичность кода, что, впрочем, не так важно. Важно другое -- это позволяет значительно уменьшить число импортов. Можно сделать синонимы для всех часто используемых классов (например из пакетов flash.display, flash.text, flash.events), описать их в одном файле, и подключать импортом только это файл, вместо того, чтобы подключать каждый из этих классов.
//файл Imports.hx
typedef Sp = flash.display.Sprite;
typedef Tf = flash.text.TextField;
//файл Test.hx
import Imports;
class Test
{
static public function main():Void
{
var s = new Sp();
s.graphics.beginFill(0xff0000, 0.5);
s.graphics.drawRect(0,0,100,100);
s.x = 10;
s.y = 10;
flash.Lib.current.addChild(s);
var tf = new Tf();
tf.border = true;
tf.text = "Hello";
flash.Lib.current.addChild(tf);
}
}
Вот это уже большая польза. Еще в ActionScript2.0 меня порой раздражают большие списки импортов в начале класса. Но там ситуация вполне терпимая. В ActionScript3.0 в этом плане вообще все хреново -- на каждый чих нужно импортировать класс. Этот фокус в haXe помогает вылечить эту болезнь.
Итераторы
Итератор это объект, который следует определению типа Iterator (T - тип итератора):
typedef Iterator<T>
{
function hasNext():Bool;
function next():T;
}
То есть, любой объект, имеющий методы hasNext и next соответствует typedef итератора
и может быть использован в цикле for напрямую:
class Foo
{
private var some:Int;
public function new()
{
this.some = 5;
}
public function hasNext():Bool
{
return this.some > 0;
}
public function next():Int
{
return --this.some;
}
}
class Test
{
static public function main():Void
{
var obj = new Foo();
for(val in obj)
{
trace(val);
}
}
}
Условная компиляция
haXe имеет специальные директивы прекомпиляции, позволяющий включать или выключать участки кода в зависимости от параметров, заданных при компиляции.
#if debug Debug.Init(this.Load); #else this.Load(); #endЭта фича уже перестала быть уникальной -- тоже самое недавно появилось во Flex3. Штука безусловно нужная, и я использую ее в своем проекте. Самое очевидное применение -- компиляция дебаг и релиз версий проекта.
Регулярные выражения
haXe кроссплатформенно поддерживает регулярные выражения. Каких-то особенностей в сравнении с тем же ActionScript3.0 не заметил.
var r:EReg = ~/world/;
var str = "hello world";
trace(r.match(str)); // true : 'world' was found in the string
trace(r.match("hello !")); // false
private конструктор
haXe поддерживает private конструктор, в отличие от ActionScript. Это позволяет создать настоящий синглтон. Если объявить конструктор класса без модификаторов доступа:
class Some
{
function new {}
}
то по умолчанию он будет private, и такой класс можно будет инстанциировать
только в статическом методе этого же класса. Поэтому нужно явно указывать
модификатор public.
class Some
{
public function new {}
}
Возможности по оптимизации производительности
Отдельно я хочу рассмотреть фишки, помогающие в повышении производительности приложения, а именно:
- inline-функции;
- Типизированные массивы;
- Параметризированные классы;
inline-функции
C inline-функциями все достаточно просто. При определении функция помечается ключевым словом inline. И потом при компиляции все вызовы функции подменяются ее телом. Это давно известная техника применяющаяся еще в языке С. И конечно она имеет известный побочный эффект -- увеличение размера сгенерированного байт-кода. Поэтому рекомендуется к применению только для небольших функций.
(В haXe еще есть и inline-свойства, но это не что иное, как константы.)
Типизированные массивы
Типизированные массивы позволяют избежать приведения типов при получении элементов из массива, и потому экономят время при доступе к ним. Я не уверен, возможно это уже есть в ActionScript3, но в haXe это было изначально.
Параметризированные классы
Наконец, параметризированные классы это очень мощная и интересная штука. Для тех, кто знаком с С++, будет видно, что это полный аналог шаблонов. Для тех, кто не знаком, нужны примеры кода, иначе трудно объяснить.
Самый простой пример -- реализация связанного списка.
class Cell {
public var elt : Dynamic;
public var next : Cell;
public function new( elt, next ) {
this.elt = elt;
this.next = next;
}
}
class List {
public var head : Cell;
public function new() {
head = null;
}
public function add( elt : Dynamic ) {
head = new Cell(elt,head);
}
}
Элементы этого списка могут хранить данные любого типа -- здесь используется Dynamic, как видите. В результате чтобы что-то сделать с этими данными, потребуется приведение типа. А чтобы этого избежать, нужно создать типизированный список.
class Cell_MyType {
public var elt : MyType;
public var next : Cell;
public function new( elt, next ) {
this.elt = elt;
this.next = next;
}
}
class List_MyType {
public var head : Cell_MyType;
public function new() {
head = null;
}
public function add( elt : MyType ) {
head = new Cell(elt,head);
}
}
Таким образом получаем связанный список, хранящий данные типа MyType. Но возникает новая проблема -- для каждого типа, который мы захотим хранить в списке, понадобится дублировать классы Cell и List. И эта проблема решается параметризированными классами.
class Cell<T> {
public var elt : T;
public var next : Cell<T>;
public function new( elt, next ) {
this.elt = elt;
this.next = next;
}
}
class List<T> {
public var head : Cell<T>;
public function new() {
head = null;
}
public function add( elt : T ) {
head = new Cell(elt,head);
}
}
var list:List<String> = new List();
list.add("some string");
var list2:List<User> = new List();
var user:User = new User();
list.add(user);
Таким образом классы Cell и List мы описываем один раз и можем использовать для любых типов, так же, как и типизированные массивы. При этом компилятор автоматически сгенерирует классы Cell_String, List_String, Cell_User, List_User. Это, конечно, тоже увеличит объем байт-кода. Такова цена высокой производительности.
В результате, haXe имеет преимущество перед ActionScript3 при написании приложений, требующих высокой производительности. Например -- 3D-движков или игр.
Примеры проектов на haXe
И напоследок — пожалуй, главный аргумент в пользу той или иной технологии, это успешный проекты, на ней сделанные. И вот они:
haxe.org
Сам сайт haxe.org сделан полностью на haXe (но без флэша). Весь сайт — одна большая wiki-система, доступная для редактирования всеми желающими. И это собственный wiki-движок, написанный Николасом. Сайт -- главный источник информации и документации по haXe. Переведен добровольцами на 10 языков, что говорит о популярности haXe на западе (и не только, ибо есть китайская и японская версии). К русскому переводу и я приложил руку.
Особенность движка wiki -- предосмотр страницы в реальном времени. По мере редактирования страницы она сразу же рендерится под формой редактирования. Ну и конечно, история изменений доступна для просмотра и управления.
comapping.com
Другой пример — comapping.com — сетевой сервис для коллективной работы над картами мышления (памяти) (Mind Maps) в реальном времени. Это закрытый коммерческий проект, и потому ссылки на него вы не найдете на haxe.org (haxe.org дает ссылки только на open source проекты).
В проекте HaXe использовался разработчиками и на сервере и в клиентской части (причем Flash). В качестве gui-библиотеки использовался ASwing
myminicity.com
myminicity.com -- составление карт городов в изометрическом мире.
prizee.com
prizee.com -- сайт с обилием флэш-игр. Все они сделаны на haXe.
Ну а вообще список проектов на haXe можно посмотреть здесь: http://haxe.org/com/projects. Обилие игр в этом разделе подтверждает, что haXe особенно хорош для их создания. Вы можете добавить туда собственный проект, если он open source.