2.5. Анонимные структуры

Ссылка на источник.
Анонимные структуры — используются для объединения данных без явного создания типа. В примере, написанном ниже, создается структура с двумя полями x и name, которые получают значения «12» и «foo» соответственно:

Общие правила синтаксиса:

  1. Структура заключается в фигурные скобки {};
  2. Пары ключ-значение разделяются запятой;
  3. Между ключом и значением ставится двоеточие;
  4. Значением может быть любое выражение на языке Haxe.

Четвертое правило говорит о том, что структуры могут быть вложенными и сложными, например:

Поля структур могут быть получены, как и классы, используя точку (.), как в примере ниже:

Также для вывода всех полей анонимной структуры, может быть использовано Reflection:

Вот что будет выведено:
name => Butterfly version => 0.3

Стоит отметить, что использование анонимных структур не подрывает, существующую в Haxe, систему типизации. Компилятор гарантирует, что доступны только существующие поля. Это означает что следующая программа не будет скомпилирована.

Полученная ошибка свидетельствует о том, что компилятор знает как был объявлен тип point : это структура с полями x и y типа Float. Поскольку поля z не существует, то доступ будет запрещен. Тип point известен благодаря определению типов. Именно ему мы должны сказать спасибо за то, что у нас нет необходимости каждый раз явно определять типы. Однако, если   point является полем, то явное определение типов обязательно:

Что бы избежать лишнего декларирования типов, особенно для более сложных структур, советуют использовать typedef:

2.1.4 Type Bool

2.1.4 Bool учебник по Haxe 3.

Bool — базовый тип, представляющий собой значение типа true или false.

Значения типа Bool обычно используют в условиях if и while.
Значения типа Bool могут возвращать такие операторы как:

  • && (и)
  • || (или)
  • ! (не).

Haxe гарантирует что сложные логические выражения вычисляются слева направо и при том только при необходимости в момент выполнения. Например, для выражения типа А && B программа первое что проверит это верно ли А,  и проверит В только в том случае если проверка для А верна. Для выражения А || B не будет вычисляться В если  А == true поскольку значение В уже не будет иметь значения. Это важно в таких случаях как например это:

if (object != null && object.field == 1) { . . . }

В этом случае, доступ в object.field приведет к ошибке во время исполнения, если поле object пусто, то есть null, но проверка object != null защитит от этой ошибки.  Другой пример:

В этом случае на выходе будет true. При этом если a > 0 && b < 0, то будет выведена строка «false».

Ссылка на Try Haxe!

5.16. Условное выражение if

Source: 5.16 if

Условные выражения начинаются с ключевого слова if  ,далее следует само условие в круглых скобках ()  и выражение, которое будет вычислено в случае выполнения условия:

Условие имеет тип Bool . Это означает, что если значение выражения, записанного в condition , является истиной true , то будет выполнено то, что далее написано в expression . Иначе — не выполнится.

После expression   может следовать ключевое слово else  для задания другого выражения, которое должно быть вычислено, если условие не выполняется:

Здесь expression2  может состоять из еще одного if  -выражения:

Если значение, вычисляемое if -выражением является необходимым для дальнейших вычислений, к примеру

то возвращаемые значения должны иметь совместимые типы. Если в данной конструкции отсутствует выражение else , возвращается выражение типа Void .

Пример. Программа сравнивает значение двух выражений:

 

5.13. Цикл for

По материалам официального руководства по Haxe 3

Haxe не поддерживает традиционные циклы $for$ из языка C. Здесь ключевое слово $for$ предполагает следующий синтаксис: вначале идет открывающая скобка $($, затем идентификатор переменной, ключевое слово $in$ и произвольное выражение, используемое в качестве итерационной коллекции. После закрывающей скобки $)$ следует тело цикла.

Программист при написании кода гарантирует, что тип $e1$ является итерируемым. Обычно это происходит в случае, если он содержит метод типа $iterator$, возвращающий $Iterator<T>$, или если он сам — $Iterator<T>$.

Переменная $v$ доступна внутри тела цикла $e2$ и хранит значения отдельных элементов коллекции $e1$.

У Haxe есть специальный оператор диапазона для итерации в пределах интервалов. Это бинарный оператор, который получает на вход два операнда типа $Int$: $min…max$, который возвращает экземпляр $IntIterator$, который итерирует от $min$ (включительно) до $max$ (не включительно). Отметим, что $max$ не должен быть меньше $min$.

Тип выражения $for$ — всегда $Void$, что означает, что оно не имеет собственного значения и не может быть использовано в качестве правой части выражения.

На управляющий поток цикла можно повлиять при помощи выражений $break$ и $continue$.

В общем, можно сказать, что цикл $for$ в Haxe напоминает циклы $foreach$ в некоторых других языках.

Пример: Программа, которая вычисляет и выводит значения $2^i$, где $i$ изменяется от 1 до 20.

Протестировать код можно здесь: Try Haxe !

5.5 Объявление массивов

Оригинал статьи.
Элементы массива разделяются запятыми , и заключаются в квадратные скобки []. Пустыми квадратными скобками [] объявляется пустой массив, в то время как [1, 2, 3] инициализирует массив с тремя элементами $1$, $2$, $3$.

Так же, как и в других языках программирования, в haxe многомерные массивы создаются на основе одномерных, у которых элементы являются массивами.

Сгенерированный код может быть менее кратким на платформах, которые не поддерживают инициализацию массива. В итоге такой код инициализации массива из трех элементов var arr = [1, 2, 3];  будет выглядеть следующим образом:

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

Пример использования массива.

Решение на Try Haxe !

10.2.3. Список

List — это коллекция для хранения элементов. На первый взгляд список похож на массив. Однако базовая реализация сильно отличается. Это приводит к нескольким функциональным отличиям:

  1. Невозможно индексировать список, используя квадратные скобки: [0].
  2. Невозможно инициализировать список.
  3. Списковое включение не поддерживается (в отличие от аналогичной возможности у массивов).
  4. Список может свободно изменять / добавлять / удалять элементы во время итерации

Простой пример работы со списками:

Связанный контент

5.14. Оператор цикла while

Ссылка на оригинальную статью.

Обычный цикл [latex]while[/latex] начинается с ключевого слова [latex]while[/latex], за которым следует открывающая скобка круглая « (», выражение условия и закрывающая скобка « )». После этого следует выражение тела цикла.

Выражение условия должно быть типа [latex]Bool[/latex].

На каждой итерации оценивается выражение условия. Если оно принимает значение [latex]false[/latex], цикл останавливается, в противном случае он вычисляет выражение тела цикла.

Этот вид цикла [latex]while[/latex] не оценивает выражение тела цикла: если условие не выполняется с самого начала, то тело цикла не вычисляется (не выполняется). Этим этот вид отличается от циклов [latex]do-while[/latex].

4.3. Методы

Ссылка на оригинальную статью.

Метод — это функция или процедура, принадлежащая какому-то классу или объекту, которая определяет поведение программы, содержащимися в  ней выражениями. Методы можно встретить в любом примере программы, даже в простом Hello World!  используется метод main.

Вот некоторые характеристики методов:

  1. Имя метода (в примере: main)
  2. Список аргументов (в примере: () )
  3. Возвращаемый тип(в примере: void )
  4. Может иметь модификации для доступа(в примере:  static и public)
  5. Может иметь выражение внутри (в примере:  {trace(«Hello World»).

Рассмотрим данный пример.

 

В данном примере есть метод toString() и конструктор, кроме main.  

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

Тип возвращаемого значения записывается после его объявления через двойные скобки. В нашем случае метод возвращает значение типа String.

У нас все методы классов Franction публичные, что значит, мы можем обращаться к ним из класса Test.

Методы и поля могут переопределены для наследников базового класса. Использование переопределения в классе подразумевает, что у него есть родительский класс. Добавим в наш пример еще один класс  — наследник  Decimal и переопределим метод базового класса toString().

Переменная d явно определена как  Fraction  и во время компиляции «узнается» как  переменная этого класса, но во время выполнения все равно находится правильный метод toString()  в классе Decimal .

Наследник может обратиться к методам родителя, которые он переопределяет с помощью вызова super.methodName(). Это используется, например, в конструкторе наследника.

Ссылка на пример на TryHaxe!