- PVSM.RU - https://www.pvsm.ru -
26 октября в г. Линц-ам-Райн (Германия) прошла мини-конференция HaxeUp Sessions 2019 [1], посвященная Haxe и смежным технологиям. И самым знаменательным ее событием был, конечно же, финальный релиз Haxe 4.0.0 (на момент публикации, то есть спустя примерно неделю, вышло обновление 4.0.1 [2]). В этом материале я хотел бы представить вам перевод первого доклада конференции — отчета о работе, проделанной командой Haxe за 2019 год.
Немного об авторе доклада:
Саймон работает с Haxe c 2010 года, когда он был еще студентом и писал работу, посвященную симуляции жидкостей во Flash. Реализация подобной симуляции требовала постоянных обращений к данным, описывающим состояние частиц (на каждом шаге осуществлялось более 100 запросов к массивам данных о состоянии каждой из ячеек в симуляции), при этом работа с массивами в ActionScript 3 не такая уж и быстрая. Поэтому первоначальная реализация попросту была нерабочей и требовалось найти решение для данной проблемы. В своих поисках Саймон натолкнулся на статью Николя Каннасса [3] (создателя Haxe), посвященную недокументированным тогда опкодам Alchemy, которые не были доступны с помощью ActionScript, но Haxe позволял их использовать. Переписав симуляцию на Haxe с использованием опкодов, Саймон получил рабочую симуляцию! И так, благодаря медленным массивам в ActionScript, Саймон узнал о Haxe.
С 2011 года Саймон присоединился к разработке Haxe, он начал изучать OCaml (на котором написан компилятор) и вносить различные исправления в работу компилятора.
А с 2012 года он стал основным разработчиком компилятора. В том же году был создан Haxe Foundation [4] (организация, основным целями которой являются развитие и поддержание экосистемы Haxe, помощь сообществу в организации конференций, консультационные услуги), и Саймон стал одним из его сооснователей.
В 2014-2015 году Саймон пригласил в Haxe Foundation Жозефину Пертозу [5], которая со временем стала отвечать за организацию конференций и связи с сообществом.
В 2016 году Саймон впервые выступил с докладом о Haxe [6], а в 2018 организовал первый HaxeUp Sessions [7].
Так что же произошло в мире Haxe за прошедший 2019 год?
В феврале и марте вышли 2 релиз-кандидата (4.0.0-rc1 и 4.0.0-rc2)
В апреле к команде Haxe Foundation присоединились Аурел Били [8] (в качестве интерна) и Александр Кузьменко [9] (в качестве разработчика компилятора).
В мае прошел Haxe US Summit 2019 [10].
В июне вышел Haxe 4.0.0-rc3. А в сентябре — Haxe 4.0.0-rc4 и Haxe 4.0.0-rc5.
Haxe — это не только компилятор, но и целый набор различных инструментов, и в течение года работа над ними также постоянно велась:
Благодаря усилиям Энди Ли [11] Haxe теперь использует Azure Pipelines вместо Travis CI и AppVeyor. Это значит, что сборка и автоматические тесты теперь выполняются гораздо быстрее.
Хью Сандерсон [12] продолжает работу над hxcpp [13] (библиотекой для поддержки C++ в Haxe).
Внезапно к работе над экстернами для Node.js присоединились пользователи Github terurou [14] и takashiski [15].
Руди Гес [16] работал над исправлениями и улучшениями для поддержки C# таргета.
Джордж Корни [17] продолжает поддержку генератора HTML-экстернов.
Йенс Фишер [18] работает над vshaxe [19] (расширение для VS Code для работы с Haxe) и над многими другими проектами, связанными с Haxe.
И главным событием года конечно же стал долгожданный релиз Haxe 4.0.0 [20] (а также neko 2.3.0), случайно совпавший с HaxeUp 2019 Linz :)
Основную часть доклада Саймон посвятил новым возможностям в Haxe 4.0.0 (о них вы также могли узнать из доклада Александра Кузьменко [21] с прошедшего Haxe US Summit 2019).
Новый интерпретатор макросов eval в несколько раз быстрее старого. Саймон подробно рассказывал о нем в своем выступлении на Haxe Summit EU 2017 [22]. Но с тех пор в нем были улучшены возможности отладки кода, исправлено множество багов, переработана реализация строк.
В Haxe 4 появилась поддержка юникод для всех платформ (кроме Neko). Подробно об этом Саймон рассказывал в своем прошлогоднем выступлении [23]. Для конечного пользователя компилятора это означает то, что выражение "Haxeは最高だぞ!".length
для всех платформ всегда будет возвращать 10
(опять же, кроме Neko).
Минимально поддерживается кодировка UCS-2 (для каждой платформы / языка используется нативно поддерживаемая кодировка; пытаться поддерживать везде одну и ту же кодировку было бы непрактично):
Все символы, находящиеся за пределами основной многоязычной плоскости (в том числе и эмодзи), представляются в виде “суррогатных пар” — такие символы представляются двумя байтами. Например, если в Java/C#/JavaScript (то есть для строк в UTF-16 и UCS-2 кодировках) запросить длину строки, состоящей из одного эмодзи, то результатом будет “2”. Этот факт нужно принимать во внимание при работе с такими строками на данных платформах.
В Haxe 4 появился новый вид итератора — “ключ-значение”:
Он работает с контейнерами типа Map
(словари) и строками (с помощью класса StringTools), поддержка для массивов пока что не реализована. Также есть возможность реализовать такой итератор для пользовательских классов, для этого достаточно реализовать для них метод keyValueIterator():KeyValueIterator<K, V>
.
Новый мета-тэг @:using
позволяет связывать статические расширения с типами по месту их объявления.
В примере, приведенном на слайде ниже, перечисление MyOption
связывается с MyOptionTools
, таким образом мы статически расширяем данное перечисление (что в обычной ситуации невозможно) и получаем возможность вызывать метод get()
, обращаясь к нему как к методу объекта.
В этом примере метод get()
является встраиваемым (inline), что также позволяет компилятору дополнительно оптимизировать код: вместо вызова метода MyOptionTools.get(myOption)
, компилятор подставит хранимое значение, то есть 12
.
Если же метод не объявлен как встраиваемый, то еще одним средством оптимизации, доступным программисту, является встраивание функций по месту их вызова (call-site inlining). Для этого при вызове функции нужно дополнительно использовать ключевое слово inline
:
Благодаря работе Даниила Коростелева [24] в Haxe появилась возможность генерации ES6-классов для JavaScript. Все что нужно для этого сделать — просто добавить флаг компиляции -D js-es=6
.
В настоящий момент компилятор генерирует один js-файл для всего проекта (возможно в будущем появится возможность генерации отдельных js-файлов для каждого из классов, но пока что это можно сделать только с помощью дополнительных инструментов [25]).
Для абстрактных перечислений теперь автоматически генерируются значения.
В Haxe 3 было необходимо вручную задавать значения для каждого конструктора. В Haxe 4 абстрактные перечисления, созданные поверх Int
, ведут себя по тем же правилам, что и в C. Аналогично ведут себя абстрактные перечисления, созданные поверх строк — для них сгенерированные значения будут совпадать с именами конструкторов.
Следует упомянуть также некоторые улучшения в синтаксисе:
@:enum
и @:extern
typedef T = A & B
означает, что структура T
имеет все поля, которые есть в типах A
и B
<T:A & B>
говорит о том, что тип параметра T
должен быть одновременно и A
и B
.
Новый синтаксис для описания типов функций (function type syntax) является более логичным: использование скобок вокруг типов аргументов функции визуально легче воспринимается. Кроме того, новый синтаксис позволяет определять имена аргументов, что можно использовать как часть документации к коду (хотя никак не влияет на саму типизацию).
Старый синтаксис при этом продолжает поддерживаться и не объявлен устаревшим, т.к. в противном случае это потребовало бы слишком много изменений в существующем коде (сам Саймон постоянно ловит себя на том, что по привычке продолжает использовать старый синтаксис).
В Haxe 4 наконец-то появились стрелочные функции (или лямбда-выражения)!
Особенностями стрелочных функций в Haxe являются:
return
. Если тело функции состоит из одного выражения, то эта функция неявно возвращает значение этого выраженияFloat
или Int
)В общем, синтаксис стрелочных функций очень похож на используемый в Java 8 (хотя и работает несколько иначе).
И раз уж мы упомянули Java, то следует сказать о том, что в Haxe 4 появилась возможность генерации JVM-байткода напрямую. Для этого при компиляции проекта под Java достаточно добавить флаг -D jvm
.
Генерация JVM-байткода означает, что необходимость использования Java-компилятора отпадает, при этом процесс компиляции осуществляется значительно быстрее.
Пока что JVM-таргет имеет статус экспериментального по следующим причинам:
Общее сравнение генерации байткода напрямую (genjvm) и компиляции Haxe в Java-код, который затем компилируется в байткод (genjava):
Общие советы при работе с Java в Haxe:
typedef
) — пока что компилятор не может оптимизировать такой кодinline
— JIT-компилятор неплохо справляется и самNull<T>
, особенно при работе со сложными математическими вычислениями. Иначе в сгенерированном коде появится множество условных операторов, что крайне негативно скажется на скорости исполнения вашего кода.Избежать использования Null<T>
может помочь новая фича Haxe 4 — Null-безопасность (Null safety). Александр Кузьменко подробно о ней рассказал на прошлогоднем HaxeUp [28].
В примере на слайде выше для статического метода safe()
включен Strict-режим проверок на Null-безопасность, при этом данный метод имеет необязательный параметр arg
, который может иметь нулевое значение. Для того, чтобы данная функция успешно скомпилировалась, программисту потребуется добавить проверку значения аргумента arg
(в противном случае компилятор выдаст сообщение о невозможности вызвать метод charAt()
у потенциально нулевого объекта).
Null-безопасность можно настраивать как на уровне пакетов (с помощью макроса), так и типов и отдельных полей объектов (с помощью мета-тэга @:nullSafety
).
Режимы, в которых работают проверки на Null-безопасность, следующий: Strict, Loose и Off. Глобально эти проверки отключены (Off-режим). При их включении по-умолчанию используется Loose-режим (если явно не указать режим). Ключевым отличием между Loose и Strict режимами является то, что Loose-режим игнорирует возможность изменения значений между операциями обращений к этим значениям. В примере на слайде ниже мы видим, что для переменной x
добавлена проверка на null
. Однако в Strict-режиме данный код не скомпилируется, т.к. перед непосредственной работой с переменной x
вызывается метод sideEffect()
, который потенциально может обнулить значение этой переменной, таким образом потребуется добавить еще одну проверку или скопировать значение переменной в локальную переменную, с которой и будем работать в дальнейшем.
В Haxe 4 появилось новое ключевое слово final
, которое в зависимости от контекста имеет различный смысл:
var
, то объявленному таким образом полю нельзя будет назначить новое значение. Задать его можно будет только напрямую при объявлении (для статических полей) или в конструкторе (для нестатических полей)
Теоретически компилятор, встретив ключевое слово final
, может попытаться оптимизировать код, предполагая, что значение данного поля не меняется. Но пока что такая возможность только рассматривается и в компиляторе не реализована.
И немного о будущем Haxe:
Автор: Zaphy
Источник [31]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/news/335460
Ссылки в тексте:
[1] мини-конференция HaxeUp Sessions 2019: https://haxe.org/videos/conferences/haxeup-sessions-2019/
[2] обновление 4.0.1: https://haxe.org/download/version/4.0.1/
[3] статью Николя Каннасса: http://ncannasse.fr/blog/virtual_memory_api
[4] Haxe Foundation: https://haxe.org/foundation/
[5] Жозефину Пертозу: https://twitter.com/Fiene_P/
[6] выступил с докладом о Haxe: https://www.youtube.com/watch?v=41Ahc-WSKaQ
[7] первый HaxeUp Sessions: https://haxe.org/videos/conferences/haxeup-sessions-2018/
[8] Аурел Били: https://github.com/Aurel300
[9] Александр Кузьменко: https://github.com/RealyUniqueName/
[10] Haxe US Summit 2019: https://haxe.org/videos/conferences/haxe-summit-us-2019/
[11] Энди Ли: https://github.com/andyli
[12] Хью Сандерсон: https://github.com/hughsando/
[13] hxcpp: https://github.com/HaxeFoundation/hxcpp
[14] terurou: https://github.com/terurou
[15] takashiski: https://github.com/takashiski
[16] Руди Гес: https://github.com/kLabz
[17] Джордж Корни: https://github.com/haxiomic
[18] Йенс Фишер: https://github.com/Gama11
[19] vshaxe: https://github.com/vshaxe/vshaxe
[20] долгожданный релиз Haxe 4.0.0: https://community.haxe.org/t/haxe-4-is-released/2102
[21] доклада Александра Кузьменко: https://habr.com/ru/post/455389/
[22] в своем выступлении на Haxe Summit EU 2017: https://haxe.org/videos/conferences/haxe-summit-2017/eval-haxe-macro-interpreter-simon-krajewski.html
[23] прошлогоднем выступлении: https://haxe.org/videos/conferences/haxeup-sessions-2018/haxe-autumn-report-simon-krajewski.html
[24] Даниила Коростелева: https://github.com/nadako/
[25] дополнительных инструментов: https://github.com/elsassph/haxe-modular
[26] MethodHandle: https://habr.com/ru/company/haulmont/blog/431922/
[27] Кауи Ванека: https://github.com/waneck
[28] на прошлогоднем HaxeUp: https://haxe.org/videos/conferences/haxeup-sessions-2018/null-safety-alexandr-kuzmenko.html
[29] оптимизация хвостовых вызовов: https://github.com/HaxeFoundation/haxe/pull/8908
[30] функции, доступные на уровне модуля: https://github.com/HaxeFoundation/haxe-evolution/blob/master/proposals/0007-module-level-funcs.md
[31] Источник: https://habr.com/ru/post/474452/?utm_campaign=474452&utm_source=habrahabr&utm_medium=rss
Нажмите здесь для печати.