Словари и наборы (перечисления)

Словарь

Словарь (:Dictionary) — набор данных произвольного типа с доступом к отдельным элементам по целочисленному индексу или по имени элемента при его наличии (это похоже и на tuple и на структуру одновременно).

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

Доступ к элементам словаря происходит по имени элемента, которое записывается через точку от имени переменной, либо по целочисленному индексу. Индекс начинается с 0 и как у тензоров, тоже может быть отрицательным (индекс элемента от “конца”).

Литерал с типом «словарь» в тексте программы записывается в круглых скобках с обязательной завершающей запятой, т. е. (,) — пустой словарь, (1, 2= «2», name=3,). Для указания конкретного типа объекта у литерала, его необходимо указать после закрывающей скобки, т.е. (1, two= «2», name=3,):Dict. Позиционный литерал без указания типа, например (1, 2, 3,), всегда является словарём (:Dictionary). Словарь — единственный универсальный тип, который может быть приведён к любому другому типу: для создания значения конкретного типа достаточно передать словарь аргументом в приведение/конструктор типа, например :Tensor[...]( (1,2,3,) ).

⚠️ НЕ РЕАЛИЗОВАНО: данный способ создания типа-словаря через `:Dict := :Dictionary() (...)` и обращения `:Dict()`/`:Dict(two=42)` в текущей версии НЕ работает. Реализован литерал `(1, two=2, name='3',)` → trust::Dict с доступом d.name / d[0] / d[i], оператором `[]=`, методом size() (см. playground/dict.src)

# Новый тип (класс) :NewClass
:Dict := :Dictionary() {
    _ := 1; # У поля данных имя отсутствует
    two := 2;
    name := 3; 
};
dict := :Dict(); # Экземпляр класса (1, two=2, name=3,):Dict
Позиционный литерал без указания типа, например `(1, 2, 3,)`, всегда является словарём (`:Dictionary`). Словарь  единственный универсальный тип, который может быть приведён к любому другому типу: для создания значения конкретного типа достаточно передать словарь аргументом в приведение/конструктор типа, например `:Tensor[...]( (1,2,3,) )`.
dict2 := :Dict(two=42); # Экземпляр класса (1, two=42, name=100,):Dict
dict3 := dict2(99, name=0); # Копия объекта dict2 (99, two=42, name=0,):Dict

В будущем можно будет добавить возможность указывать индексы элементов словаря с помощь диапазонов

$dict = :Dict[10](first=1, 4..4 = 29, 2..3 = 15, , 2..3 = 15, 7..9..2 = 7); #(first=1, 0, 15, 15, 29, 0, 0, 7, 0, 7,)

Перечисление (Enum)

Enum — тип данных с ограниченным списком членов, у каждого из которых есть имя и значение. Все члены перечисления имеют единый тип значений (valueType), который выводится по общим правилам (из значений членов либо из явной аннотации типа).

Литерал-объявление записывается в постфиксной форме (члены,):Enum или префиксной :Enum(члены) (как у типизированного кортежа). Обязательная завершающая запятая — как у словаря.

    # Члены с явными значениями; тип значений — Int64 (по общим правилам)
    Status ::= (OK=0, ERROR=1, BUSY=2,):Enum;

    # Безнарные члены — автоинкремент от 0: RED=0, GREEN=1, BLUE=2
    Color ::= (RED, GREEN, BLUE,):Enum;

    # Явный тип члена задаёт единый тип значений — Int8 (безнарные → автоинкремент)
    Flag ::= (LOW:Int8, HIGH,):Enum;

⚠️ НЕ РЕАЛИЗОВАНО: оператор `::=` здесь используется корректно (объявление типа Enum); проверено компилятором. Однако доступ к членам через `Status.OK` и методы `count()`/`fromName()`/`fromValue()` в текущей версии реализованы не полностью (например `Status.count()` даёт ошибку 'type Enum has no method count')

По умолчанию тип значений выводится из явных значений членов (resolvedType + join по общим правилам); если явных значений нет — минимальный знаковый целый по числу членов. Явная аннотация типа члена (name:Type) задаёт тип значений принудительно (у всех членов он должен быть одинаковым). Сравнение членов идёт по значению (value), а не по позиции (IntEnum-семантика).

Классические методы (работают через имя типа):

  • count() — число членов;
  • fromName(name) — член по имени;
  • fromValue(value) — член по значению.

Обращение к члену — через имя типа: Status.OK.

Вариант (Variant)

Variant — гетерогенный тип: каждый член имеет свой тип данных (аналог std::variant). Тип члена задаётся явной аннотацией (name:Type) либо выводится из его значения; для безнарного члена без типа — минимальный знаковый целый по позиции.

    Data ::= (i=42, s='text', r=1\2,):Variant;   # типы членов: Int8, StrChar, Rational
    V    ::= (X:Int64=7, Y:Rational,):Variant;   # явные типы членов

⚠️ НЕ РЕАЛИЗОВАНО: оператор `::=` здесь используется корректно (объявление типа Variant); проверено компилятором

Классический метод: count() — число членов. Обращение к члену: Data.i (тип — тип конкретного члена, гетерогенный).