> 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` — изменяемый по размеру список с `count` и `capacity`.

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

list: [..]int;
list.append(10);
list.append(20);
```

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

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

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

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

```go
players_seen: [..]string;
players_seen.append(player.get_user_id());
```

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

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

```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, не включая count»:

```go
for i: 0..<inventory.capacity {
    item := inventory.get_item(i);
    if item == null continue;
    // ...
}
```

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

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

```go
for i: 0..<inventory.capacity #reverse {
    item := inventory.get_item(i);
    if item == null continue;
    // ...
}
```

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

Используйте `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: %", {score});
}

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

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

## Замыкания, колбэки и userdata (важно)

CSL не **Не** поддерживает замыкания. Встроенные `proc() { ... }` определения не могут захватывать переменные из окружающей области видимости.

Когда вам нужны колбэки (обработчики UI, хуки смерти и т. д.), связывайте колбэк с `полем userdata: Object` поля.

```go
Button_Handler :: class {
    clicks: int;
}

UI_Button :: class {
    on_click_userdata: Object;
    on_click: proc(userdata: Object);
}

setup :: proc(btn: UI_Button, handler: Button_Handler) {
    btn.on_click_userdata = handler;
    btn.on_click = proc(userdata: Object) {
        h := userdata.(Button_Handler);
        h.clicks += 1;
    };
}
```

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

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