> For the complete documentation index, see [llms.txt](https://docs.allout.game/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.allout.game/all-out-docs/ru/skripting/arrays-and-collections.md).

# Расширенный справочник по языку

CSL даёт вам несколько инструментов, похожих на массивы, которые покрывают большинство игровых задач: фиксированные массивы, срезы и динамические массивы. Эта страница — практическое руководство по их использованию без подводных камней.

## Краткий глоссарий

* **Фиксированный массив**: `[N]T` — размер известен на этапе компиляции.
* **Срез / управляемый массив**: `[]T` — представление данных массива (часто используется для параметров).
* **Динамический массив**: `[..]T` — изменяемый по размеру список с `количеством` и `ёмкостью`.

```go
fixed: [4]int = {1, 2, 3, 4};
view: []int = fixed; // представление среза

list: [..]int = {10, 20};
```

{% hint style="info" %}
Методы динамических массивов вызываются обычной точечной записью (например, `list.append(x)`). Поля тоже доступны через точку (например, `list.count`).
{% endhint %}

## Динамические массивы (`[..]T`)

Динамические массивы — это тип списка «по умолчанию» для игрового кода.

### Создание и добавление

```go
players_seen: [..]string = {"Ada", "Grace"};
players_seen.append(player.get_user_id());
```

Литералы динамических массивов могут содержать выражения времени выполнения и могут возвращаться напрямую, когда ожидаемый тип — `[..]T`:

```go
make_values :: proc(seed: int) -> [..]int {
    return {seed, seed + 1};
}
```

Также поддерживаются значения по умолчанию для полей класса с динамическими массивами. Каждый экземпляр класса получает независимое изменяемое хранилище:

```go
Loadout :: class {
    slots: [..]string = {"sword", "potion"};
}
```

### Резервирование ёмкости (производительность)

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

```go
results: [..]Enemy;
results.reserve(128);
```

### Удаление элементов

Обычно выбирают между **быстрым удалением** (порядок не важен) и **упорядоченным удалением** (с сохранением порядка).

```go
values: [..]int;
values.append(10);
values.append(20);
values.append(30);

values.unordered_remove_by_value(20); // меняет местами с последним, быстро
values.ordered_remove_by_value(10);   // сдвигает, сохраняет порядок
```

Также можно удалять по индексу:

```go
values.unordered_remove_by_index(0);
values.ordered_remove_by_index(0);
```

### Очистка

```go
values.clear(); // O(1): просто устанавливает count в 0
```

## Передача массивов в процедуры

Многие API принимают `[]T` (срез/представление). Динамические массивы можно передавать туда, где ожидается `[]T` .

```go
sum :: proc(arr: []int) -> int {
    total := 0;
    for v: arr {
        total += v;
    }
    return total;
}

nums: [..]int;
nums.append(1);
nums.append(2);
nums.append(3);

total := sum(nums); // неявно [..]int -> []int
```

## Паттерны итерации

### Итерация по элементам

```go
for v: nums {
    log_info("v=%", {v});
}
```

### Итерация по индексам

Используйте `..<` когда нужен обычный цикл «от 0 до, но не включая, count»:

```go
for i: 0..<nums.count {
    log_info("nums[%]=%", {i, nums[i]});
}
```

Некоторые коллекции движка предоставляют итераторы. `inventory.slots()` проходит по каждому слоту по порядку, выдаёт `null` для пустых слотов и показывает фактический слот как необязательный индекс:

```go
for item, slot: inventory.slots() if item != null {
    log_info("предмет % находится в слоте %", {item.get_definition().id, slot});
}
```

{% hint style="warning" %}
`..` диапазоны включительные. `..<` диапазоны исключают верхнюю границу.
{% endhint %}

Обратные циклы используют `#reverse`:

```go
for i: 0..<nums.count #reverse {
    log_info("nums[%]=%", {i, nums[i]});
}
```

## Хеш-таблицы

Используйте `Hashtable(Key_Type, Value_Type)` когда нужен быстрый поиск по ключу. Она поддерживает целочисленные и строковые ключи, а также обычные методы для поиска, вставки, перезаписи, удаления и итерации.

```go
scores: Hashtable(string, s64);
scores.add("alice", 10);
scores.add_or_overwrite("bob", 25);

score, ok := scores.find("alice");
if ok {
    log_info("счёт alice: %", {score});
}

for value, key: scores {
    log_info("% = %", {key, value});
}
```

Используйте `add` когда дублирующиеся ключи должны вызывать assert. Используйте `add_or_overwrite` когда ожидается обновление существующего ключа. `try_add` возвращает `true` если ключ уже существовал, и оставляет старое значение без изменений.

## Замыкания и обратные вызовы

Литералы процедур могут захватывать окружающие значения, но захватывающие процедуры являются выражениями обратного вызова и не могут храниться в коллекциях или других местах. Параметр процедуры должен быть помечен `#no_captures` перед тем как его можно будет хранить, и тогда вызывающие стороны смогут передавать только незахватывающие процедуры; см. [Замыкания и обратные вызовы](/all-out-docs/ru/skripting/syntax.md#closures-and-callbacks) правила использования и шаблон с явным userdata.

## Справочник по API

Каждый проект включает `api_references/` папку, содержащую текущий основной API. Откройте соответствующий `.csl_engine` файл, чтобы просмотреть тип или процедуру.
