semantic-typescript 0.5.3 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/asynchronous/collector.d.ts +231 -0
- package/dist/asynchronous/collector.js +800 -0
- package/dist/asynchronous/semantic.d.ts +257 -0
- package/dist/asynchronous/semantic.js +1853 -0
- package/dist/factory.d.ts +71 -37
- package/dist/factory.js +443 -262
- package/dist/guard.d.ts +24 -14
- package/dist/guard.js +73 -19
- package/dist/hook.d.ts +6 -6
- package/dist/hook.js +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/optional.d.ts +2 -2
- package/dist/symbol.d.ts +19 -10
- package/dist/symbol.js +19 -10
- package/dist/synchronous/collector.d.ts +232 -0
- package/dist/{collector.js → synchronous/collector.js} +160 -151
- package/dist/{semantic.d.ts → synchronous/semantic.d.ts} +111 -120
- package/dist/{semantic.js → synchronous/semantic.js} +299 -337
- package/dist/utility.d.ts +7 -1
- package/dist/utility.js +1 -0
- package/package.json +1 -1
- package/readme.cn.md +158 -697
- package/readme.de.md +163 -432
- package/readme.es.md +163 -433
- package/readme.fr.md +162 -444
- package/readme.jp.md +162 -442
- package/readme.kr.md +161 -430
- package/readme.md +157 -1009
- package/readme.ru.md +161 -426
- package/readme.tw.md +161 -436
- package/dist/collector.d.ts +0 -236
- package/dist/main.d.ts +0 -1
- package/dist/main.js +0 -4
- package/dist/map.d.ts +0 -76
- package/dist/map.js +0 -245
- package/dist/node.d.ts +0 -182
- package/dist/node.js +0 -918
- package/dist/set.d.ts +0 -19
- package/dist/set.js +0 -65
- package/dist/tree.d.ts +0 -82
- package/dist/tree.js +0 -257
package/readme.ru.md
CHANGED
|
@@ -1,470 +1,205 @@
|
|
|
1
|
-
# Библиотека потоковой
|
|
1
|
+
# Semantic-TypeScript: Библиотека потоковой обработки, меняющая парадигму
|
|
2
2
|
|
|
3
3
|
## Введение
|
|
4
|
+
Semantic-TypeScript представляет собой значительный прогресс в технологии потоковой обработки, синтезируя наиболее эффективные концепции из JavaScript GeneratorFunctions, Java Streams и парадигм индексации баз данных. Его фундаментальный принцип проектирования сосредоточен на построении исключительно эффективных конвейеров обработки данных с помощью сложных вычислений с отложенным выполнением (lazy evaluation) и интеллектуальной индексации. Библиотека предоставляет строго типобезопасный, функционально чистый опыт работы с потоками, специально созданный для современной разработки на TypeScript и JavaScript.
|
|
4
5
|
|
|
5
|
-
Semantic-TypeScript
|
|
6
|
+
В отличие от традиционных синхронных архитектур обработки, Semantic-TypeScript реализует унифицированную модель, которая изящно обрабатывает как синхронные (Iterable), так и асинхронные (AsyncIterable) источники данных. Во время генерации потока поток и завершение данных точно контролируются механизмами обратных вызовов (callback), что позволяет библиотеке исключительно элегантно обрабатывать:
|
|
7
|
+
* Потоки данных в реальном времени (события DOM, WebSockets, интервалы) с детерминированным управлением
|
|
8
|
+
* Большие наборы данных с помощью эффективных по памяти, "ленивых" (lazy) конвейеров
|
|
9
|
+
* Сложные преобразования данных с помощью беглого, декларативного API
|
|
6
10
|
|
|
7
|
-
|
|
11
|
+
Инновационный подход библиотеки фундаментально переосмысливает то, как разработчики взаимодействуют с последовательностями данных, предоставляя как беспрецедентные характеристики производительности, так и эргономику для разработчиков в едином, целостном пакете.
|
|
8
12
|
|
|
9
|
-
##
|
|
13
|
+
## Основная философия: разделение определения и выполнения
|
|
14
|
+
Ключевая архитектурная идея Semantic-TypeScript — это четкое разделение между определением потока и его выполнением:
|
|
15
|
+
* **Semantic<E>**: неизменяемый, "ленивый" (lazy) план конвейера преобразования данных. Он определяет, какие операции (filter, map и т.д.) будут выполнены.
|
|
16
|
+
* **Collectable<E>**: материализованное, исполняемое представление потока. Получается из Semantic и предоставляет все терминальные операции (collect, forEach и т.д.) для выполнения конвейера и получения результата.
|
|
10
17
|
|
|
11
|
-
|
|
12
|
-
npm install semantic-typescript
|
|
13
|
-
```
|
|
18
|
+
Это разделение обеспечивает четкую ментальную модель и открывает возможность мощных оптимизаций, таких как выбор UnorderedCollectable для пропуска ненужной сортировки для максимальной скорости.
|
|
14
19
|
|
|
15
|
-
##
|
|
16
|
-
|
|
17
|
-
| Тип | Описание |
|
|
18
|
-
|------|-------------|
|
|
19
|
-
| `Invalid<T>` | Тип, расширяющий `null` или `undefined` |
|
|
20
|
-
| `Valid<T>` | Тип, исключающий `null` и `undefined` |
|
|
21
|
-
| `MaybeInvalid<T>` | Тип, который может быть `null` или `undefined` |
|
|
22
|
-
| `Primitive` | Коллекция примитивных типов |
|
|
23
|
-
| `MaybePrimitive<T>` | Тип, который может быть примитивным типом |
|
|
24
|
-
| `OptionalSymbol` | Символьный идентификатор класса `Optional` |
|
|
25
|
-
| `SemanticSymbol` | Символьный идентификатор класса `Semantic` |
|
|
26
|
-
| `CollectorsSymbol` | Символьный идентификатор класса `Collector` |
|
|
27
|
-
| `CollectableSymbol` | Символьный идентификатор класса `Collectable` |
|
|
28
|
-
| `OrderedCollectableSymbol` | Символьный идентификатор класса `OrderedCollectable` |
|
|
29
|
-
| `WindowCollectableSymbol` | Символьный идентификатор класса `WindowCollectable` |
|
|
30
|
-
| `StatisticsSymbol` | Символьный идентификатор класса `Statistics` |
|
|
31
|
-
| `NumericStatisticsSymbol` | Символьный идентификатор класса `NumericStatistics` |
|
|
32
|
-
| `BigIntStatisticsSymbol` | Символьный идентификатор класса `BigIntStatistics` |
|
|
33
|
-
| `UnorderedCollectableSymbol` | Символьный идентификатор класса `UnorderedCollectable` |
|
|
34
|
-
|
|
35
|
-
## Функциональные интерфейсы
|
|
36
|
-
|
|
37
|
-
| Интерфейс | Описание |
|
|
38
|
-
|-----------|-------------|
|
|
39
|
-
| `Runnable` | Функция без параметров и без возвращаемого значения |
|
|
40
|
-
| `Supplier<R>` | Функция без параметров, возвращающая `R` |
|
|
41
|
-
| `Functional<T, R>` | Функция одного параметра для преобразования |
|
|
42
|
-
| `BiFunctional<T, U, R>` | Функция двух параметров для преобразования |
|
|
43
|
-
| `TriFunctional<T, U, V, R>` | Функция трех параметров для преобразования |
|
|
44
|
-
| `Predicate<T>` | Функция одного параметра для утверждения |
|
|
45
|
-
| `BiPredicate<T, U>` | Функция двух параметров для утверждения |
|
|
46
|
-
| `TriPredicate<T, U, V>` | Функция трех параметров для утверждения |
|
|
47
|
-
| `Consumer<T>` | Функция одного параметра для потребления |
|
|
48
|
-
| `BiConsumer<T, U>` | Функция двух параметров для потребления |
|
|
49
|
-
| `TriConsumer<T, U, V>` | Функция трех параметров для потребления |
|
|
50
|
-
| `Comparator<T>` | Функция двух параметров для сравнения |
|
|
51
|
-
| `Generator<T>` | Функция генератора (основа и фундамент) |
|
|
20
|
+
## Почему стоит выбрать Semantic-TypeScript?
|
|
21
|
+
Выбор подходящей библиотеки для обработки потоков данных предполагает баланс между производительностью, типобезопасностью и выразительностью. Semantic-TypeScript создан для превосходства по всем этим параметрам.
|
|
52
22
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
let predicate: Predicate<number> = (n: number): boolean => n > 0;
|
|
56
|
-
let mapper: Functional<string, number> = (text: string): number => text.length;
|
|
57
|
-
let comparator: Comparator<number> = (a: number, b: number): number => a - b;
|
|
58
|
-
```
|
|
23
|
+
### 1. Унифицированная, типобезопасная парадигма для всех последовательностей данных
|
|
24
|
+
Он предоставляет единый, декларативный API для обработки любой последовательности данных — будь то статические массивы, события в реальном времени или асинхронные фрагменты (chunks) — при этом используя всю мощь TypeScript для обеспечения сквозной типобезопасности. Это устраняет целый класс ошибок времени выполнения и превращает манипуляции с потоками в предсказуемую, проверяемую компилятором деятельность.
|
|
59
25
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
| Функция | Описание | Временная сложность | Пространственная сложность |
|
|
63
|
-
|------|------|------------|------------|
|
|
64
|
-
| `validate<T>(t: MaybeInvalid<T>): t is T` | Проверить, что значение не является null или undefined | O(1) | O(1) |
|
|
65
|
-
| `invalidate<T>(t: MaybeInvalid<T>): t is null \| undefined` | Проверить, что значение является null или undefined | O(1) | O(1) |
|
|
66
|
-
| `isBoolean(t: unknown): t is boolean` | Проверить, является ли это булевым значением | O(1) | O(1) |
|
|
67
|
-
| `isString(t: unknown): t is string` | Проверить, является ли это строкой | O(1) | O(1) |
|
|
68
|
-
| `isNumber(t: unknown): t is number` | Проверить, является ли это числом | O(1) | O(1) |
|
|
69
|
-
| `isFunction(t: unknown): t is Function` | Проверить, является ли это функцией | O(1) | O(1) |
|
|
70
|
-
| `isObject(t: unknown): t is object` | Проверить, является ли это объектом | O(1) | O(1) |
|
|
71
|
-
| `isSymbol(t: unknown): t is symbol` | Проверить, является ли это символом | O(1) | O(1) |
|
|
72
|
-
| `isBigint(t: unknown): t is bigint` | Проверить, является ли это BigInt | O(1) | O(1) |
|
|
73
|
-
| `isPrimitive(t: unknown): t is Primitive` | Проверить, является ли это примитивным типом | O(1) | O(1) |
|
|
74
|
-
| `isIterable(t: unknown): t is Iterable<unknown>` | Проверить, является ли это итерируемым объектом | O(1) | O(1) |
|
|
75
|
-
| `isOptional(t: unknown): t is Optional<unknown>` | Проверить, является ли это экземпляром Optional | O(1) | O(1) |
|
|
76
|
-
| `isSemantic(t: unknown): t is Semantic<unknown>` | Проверить, является ли это экземпляром Semantic | O(1) | O(1) |
|
|
77
|
-
| `isCollector(t: unknown): t is Collector<unknown, unknown, unknown>` | Проверить, является ли это экземпляром Collector | O(1) | O(1) |
|
|
78
|
-
| `isCollectable(t: unknown): t is Collectable<unknown>` | Проверить, является ли это экземпляром Collectable | O(1) | O(1) |
|
|
79
|
-
| `isOrderedCollectable(t: unknown): t is OrderedCollectable<unknown>` | Проверить, является ли это экземпляром OrderedCollectable | O(1) | O(1) |
|
|
80
|
-
| `isWindowCollectable(t: unknown): t is WindowCollectable<unknown>` | Проверить, является ли это экземпляром WindowCollectable | O(1) | O(1) |
|
|
81
|
-
| `isUnorderedCollectable(t: unknown): t is UnorderedCollectable<unknown>` | Проверить, является ли это экземпляром UnorderedCollectable | O(1) | O(1) |
|
|
82
|
-
| `isStatistics(t: unknown): t is Statistics<unknown, number \| bigint>` | Проверить, является ли это экземпляром Statistics | O(1) | O(1) |
|
|
83
|
-
| `isNumericStatistics(t: unknown): t is NumericStatistics<unknown>` | Проверить, является ли это экземпляром NumericStatistics | O(1) | O(1) |
|
|
84
|
-
| `isBigIntStatistics(t: unknown): t is BigIntStatistics<unknown>` | Проверить, является ли это экземпляром BigIntStatistics | O(1) | O(1) |
|
|
85
|
-
| `isPromise(t: unknown): t is Promise<unknown>` | Проверить, является ли это объектом Promise | O(1) | O(1) |
|
|
86
|
-
| `isAsync(t: unknown): t is AsyncFunction` | Проверить, является ли это AsyncFunction | O(1) | O(1) |
|
|
26
|
+
### 2. Непреклонная производительность с интеллектуальной "ленивостью" (Laziness)
|
|
27
|
+
В своей основе библиотека построена на отложенном выполнении (lazy evaluation). Операции, такие как filter, map и flatMap, лишь составляют конвейер обработки; никакая работа не выполняется до тех пор, пока не будет вызвана терминальная операция. Это сочетается с возможностями короткого замыкания (short-circuiting) (через limit, anyMatch или пользовательские прерывающие обратные вызовы), что позволяет остановить обработку досрочно, значительно повышая эффективность для больших или бесконечных потоков.
|
|
87
28
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
let value: unknown = "hello";
|
|
29
|
+
### 3. Сила паттерна `Collector<E, A, R>`
|
|
30
|
+
Вдохновленный Java, паттерн Collector — это двигатель гибкости. Он отделяет спецификацию того, как накапливать элементы потока, от самого выполнения потока. Библиотека предоставляет богатый набор встроенных коллекторов (collectors) (toArray, groupBy, summate и т.д.) для повседневных задач, позволяя при этом с легкостью реализовывать собственную сложную, повторно используемую логику свёртки (reduction). Это намного мощнее и композируемее, чем фиксированный набор терминальных методов.
|
|
91
31
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
if(isIterable(value)){
|
|
101
|
-
// Типобезопасно, теперь это итерируемый объект.
|
|
102
|
-
for(let item of value){
|
|
103
|
-
console.log(item);
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
```
|
|
32
|
+
### 4. Поддержка современного веба и асинхронных данных "из коробки"
|
|
33
|
+
Semantic-TypeScript создан для современной разработки. Он предлагает нативные фабричные методы для современных веб-источников:
|
|
34
|
+
* `useFrom(iterable)`, `useRange()` для статических данных
|
|
35
|
+
* `useInterval()`, `useAnimationFrame()` для потоков, основанных на времени
|
|
36
|
+
* `useBlob()` для обработки бинарных данных фрагментами (chunked)
|
|
37
|
+
* `useWebSocket()`, `useDocument()`, `useWindow()` для потоков событий в реальном времени
|
|
107
38
|
|
|
108
|
-
|
|
39
|
+
### 5. За пределами базовой агрегации: встроенный статистический анализ
|
|
40
|
+
Выходите за рамки простых сумм и средних значений. Библиотека предоставляет специальные интерфейсы NumericStatistics и BigIntStatistics, предлагая немедленный доступ к расширенным статистическим показателям напрямую из ваших потоков — дисперсия, стандартное отклонение, медиана, асимметрия (skewness) и эксцесс (kurtosis). Это превращает сложный анализ данных в однострочник.
|
|
109
41
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
42
|
+
### 6. Спроектирован с учетом эргономики разработчика
|
|
43
|
+
* **Беглый, цепочечный (chainable) API**: Пишите сложные конвейеры данных в виде читаемых, последовательных цепочек.
|
|
44
|
+
* **Комплексный набор утилит**: Включены основные защиты (isFunction, isIterable), утилиты (useCompare, useTraverse) и функциональные интерфейсы.
|
|
45
|
+
* **Интеграция с Optional<T>**: Безопасно моделирует отсутствие значения, устраняя проблемы с нулевыми указателями (null-pointer).
|
|
46
|
+
* **Рекомендации по производительности**: Четкие указания, когда использовать неупорядоченную (unordered) коллекцию для скорости, а когда упорядоченную (ordered) для последовательности.
|
|
114
47
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
numbers.sort(useCompare); // [1, 1, 3, 4, 5]
|
|
119
|
-
|
|
120
|
-
let randomNum = useRandom(42); // Случайное число на основе семени
|
|
48
|
+
## Установка
|
|
49
|
+
```bash
|
|
50
|
+
npm install semantic-typescript
|
|
121
51
|
```
|
|
122
52
|
|
|
123
|
-
##
|
|
124
|
-
|
|
125
|
-
### Методы фабрики Optional
|
|
126
|
-
|
|
127
|
-
| Метод | Описание | Временная сложность | Пространственная сложность |
|
|
128
|
-
|------|------|------------|------------|
|
|
129
|
-
| `Optional.empty<T>()` | Создание пустого Optional | O(1) | O(1) |
|
|
130
|
-
| `Optional.of<T>(value)` | Создание Optional с содержимым | O(1) | O(1) |
|
|
131
|
-
| `Optional.ofNullable<T>(value)` | Создание потенциально пустого Optional | O(1) | O(1) |
|
|
132
|
-
| `Optional.ofNonNull<T>(value)` | Создание не-пустого Optional | O(1) | O(1) |
|
|
53
|
+
## Основные концепции на практике
|
|
133
54
|
|
|
55
|
+
### 1. Создание потоков (Semantic)
|
|
56
|
+
Потоки можно создавать из различных источников с помощью фабричных функций.
|
|
134
57
|
```typescript
|
|
135
|
-
|
|
136
|
-
let empty: Optional<number> = Optional.empty();
|
|
137
|
-
let present: Optional<number> = Optional.of(42);
|
|
138
|
-
let nullable: Optional<string> = Optional.ofNullable<string>(null);
|
|
139
|
-
let nonNull: Optional<string> = Optional.ofNonNull("hello");
|
|
140
|
-
|
|
141
|
-
presentOpt.ifPresent((val: number): void => console.log(val)); // Выводит 42
|
|
142
|
-
console.log(emptyOpt.get(100)); // Выводит 100
|
|
143
|
-
```
|
|
58
|
+
import { useFrom, useInterval, useDocument } from 'semantic-typescript';
|
|
144
59
|
|
|
145
|
-
|
|
60
|
+
// Из статического массива
|
|
61
|
+
const staticStream = useFrom([1, 2, 3, 4, 5]);
|
|
146
62
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
63
|
+
// Из асинхронного генератора
|
|
64
|
+
const asyncStream = useFrom(async function*() {
|
|
65
|
+
yield 1;
|
|
66
|
+
yield 2;
|
|
67
|
+
});
|
|
151
68
|
|
|
152
|
-
|
|
153
|
-
//
|
|
154
|
-
let numbers = from([3, 1, 4, 1, 5, 9, 2, 6, 5]);
|
|
155
|
-
|
|
156
|
-
// Приоритет производительности: использование неупорядоченного коллектора для лучшей производительности
|
|
157
|
-
let unordered = numbers
|
|
158
|
-
.filter((n: number): boolean => n > 3)
|
|
159
|
-
.toUnordered(); // Лучшая производительность
|
|
160
|
-
|
|
161
|
-
// Необходимость в сортировке: использование упорядоченного коллектора
|
|
162
|
-
let ordered = numbers.sorted();
|
|
163
|
-
|
|
164
|
-
// Подсчет элементов
|
|
165
|
-
let count = Collector.full(
|
|
166
|
-
(): number => 0, // Начальное значение
|
|
167
|
-
(accumulator: number, element: number): number => accumulator + element, // Аккумуляция
|
|
168
|
-
(accumulator: number): number => accumulator // Завершение
|
|
169
|
-
);
|
|
170
|
-
count.collect(from([1,2,3,4,5])); // Подсчет из потока
|
|
171
|
-
count.collect([1,2,3,4,5]); // Подсчет из итерируемого объекта
|
|
172
|
-
|
|
173
|
-
let find = Collector.shortable(
|
|
174
|
-
(): Optional<number> => Optional.empty(), // Начальное значение
|
|
175
|
-
(element: number, index: bigint, accumulator: Optional<number>): Optional<number> => accumulator.isPresent(), // Прерывание
|
|
176
|
-
(accumulator: Optional<number>, element: number, index: bigint): Optional<number> => Optional.of(element), // Аккумуляция
|
|
177
|
-
(accumulator: Optional<number>): Optional<number> => accumulator // Завершение
|
|
178
|
-
);
|
|
179
|
-
find.collect(from([1,2,3,4,5])); // Находит первый элемент
|
|
180
|
-
find.collect([1,2,3,4,5]); // Находит первый элемент
|
|
181
|
-
```
|
|
69
|
+
// Поток на основе времени
|
|
70
|
+
const tickStream = useInterval(1000); // испускает значение каждую секунду
|
|
182
71
|
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
| Метод | Описание | Временная сложность | Пространственная сложность |
|
|
186
|
-
|------|------|------------|------------|
|
|
187
|
-
| `animationFrame(period: number, delay: number = 0)` | Создание потока на основе анимационных кадров | O(1)* | O(1) |
|
|
188
|
-
| `blob(blob, chunkSize)` | Создание потока из Blob | O(n) | O(chunkSize) |
|
|
189
|
-
| `empty<E>()` | Создание пустого потока | O(1) | O(1) |
|
|
190
|
-
| `fill<E>(element, count)` | Создание заполненного потока | O(n) | O(1) |
|
|
191
|
-
| `from<E>(iterable)` | Создание потока из итерируемого объекта | O(1) | O(1) |
|
|
192
|
-
| `interval(period, delay?)` | Создание временного интервального потока | O(1)* | O(1) |
|
|
193
|
-
| `iterate<E>(generator)` | Создание потока из генератора | O(1) | O(1) |
|
|
194
|
-
| `range(start, end, step)` | Создание потока числового диапазона | O(n) | O(1) |
|
|
195
|
-
| `websocket(websocket)` | Создание потока из WebSocket | O(1) | O(1) |
|
|
196
|
-
|
|
197
|
-
```typescript
|
|
198
|
-
// Примеры использования фабричных методов Semantic
|
|
199
|
-
|
|
200
|
-
// Создание потока из Blob (чтение блоками)
|
|
201
|
-
blob(someBlob, 1024n)
|
|
202
|
-
.toUnordered()
|
|
203
|
-
.write(WritableStream)
|
|
204
|
-
.then(callback) // Успешная запись потока
|
|
205
|
-
.catch(callback); // Ошибка записи потока
|
|
206
|
-
|
|
207
|
-
// Создание пустого потока, который не будет выполнен до объединения с другими потоками
|
|
208
|
-
empty<string>()
|
|
209
|
-
.toUnordered()
|
|
210
|
-
.join(); // []
|
|
211
|
-
|
|
212
|
-
// Создание заполненного потока
|
|
213
|
-
const filledStream = fill("hello", 3); // "hello", "hello", "hello"
|
|
214
|
-
|
|
215
|
-
// Создание временного потока с начальной задержкой в 2 секунды и периодом выполнения в 5 секунд, реализованного на основе механизма таймера; может возникать временной дрейф из-за ограничений точности системного планирования.
|
|
216
|
-
const intervalStream = interval(5000, 2000);
|
|
217
|
-
|
|
218
|
-
// Создание потока из итерируемого объекта
|
|
219
|
-
const numberStream = from([1, 2, 3, 4, 5]);
|
|
220
|
-
const stringStream = from(new Set(["Alex", "Bob"]));
|
|
221
|
-
|
|
222
|
-
// Создание потока числового диапазона
|
|
223
|
-
const rangeStream = range(1, 10, 2); // 1, 3, 5, 7, 9
|
|
224
|
-
|
|
225
|
-
// Поток событий WebSocket
|
|
226
|
-
const ws = new WebSocket("ws://localhost:8080");
|
|
227
|
-
websocket(ws)
|
|
228
|
-
.filter((event): boolean => event.type === "message") // Слушать только сообщения
|
|
229
|
-
.toUnordered() // Обычно события неупорядочены
|
|
230
|
-
.forEach((event): void => receive(event)); // Получение сообщений
|
|
72
|
+
// Поток событий DOM (см. важное примечание ниже)
|
|
73
|
+
const clickStream = useDocument('click');
|
|
231
74
|
```
|
|
232
75
|
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
| Метод | Описание | Временная сложность | Пространственная сложность |
|
|
236
|
-
|------|------|------------|------------|
|
|
237
|
-
| `concat(other)` | Объединение двух потоков | O(n) | O(1) |
|
|
238
|
-
| `distinct()` | Удаление дубликатов | O(n) | O(n) |
|
|
239
|
-
| `distinct(comparator)` | Удаление дубликатов с использованием компаратора | O(n²) | O(n) |
|
|
240
|
-
| `dropWhile(predicate)` | Отброс элементов, удовлетворяющих условию | O(n) | O(1) |
|
|
241
|
-
| `filter(predicate)` | Фильтрация элементов | O(n) | O(1) |
|
|
242
|
-
| `flat(mapper)` | Плоское отображение | O(n × m) | O(1) |
|
|
243
|
-
| `flatMap(mapper)` | Отображение в новый тип | O(n × m) | O(1) |
|
|
244
|
-
| `limit(n)` | Ограничение количества элементов | O(n) | O(1) |
|
|
245
|
-
| `map(mapper)` | Преобразование картой | O(n) | O(1) |
|
|
246
|
-
| `peek(consumer)` | Просмотр элементов | O(n) | O(1) |
|
|
247
|
-
| `redirect(redirector)` | Перенаправление индекса | O(n) | O(1) |
|
|
248
|
-
| `reverse()` | Обращение потока | O(n) | O(1) |
|
|
249
|
-
| `shuffle()` | Случайная перестановка | O(n) | O(1) |
|
|
250
|
-
| `shuffle(mapper)` | Перестановка с использованием маппера | O(n) | O(1) |
|
|
251
|
-
| `skip(n)` | Пропуск первых n элементов | O(n) | O(1) |
|
|
252
|
-
| `sorted()` | Сортировка | O(n log n) | O(n) |
|
|
253
|
-
| `sorted(comparator)` | Сортировка с использованием компаратора | O(n log n) | O(n) |
|
|
254
|
-
| `sub(start, end)` | Получение подпотока | O(n) | O(1) |
|
|
255
|
-
| `takeWhile(predicate)` | Получение элементов, удовлетворяющих условию | O(n) | O(1) |
|
|
256
|
-
| `translate(offset)` | Перевод индекса | O(n) | O(1) |
|
|
257
|
-
| `translate(translator)` | Перевод индекса с использованием транслятора | O(n) | O(1) |
|
|
258
|
-
|
|
76
|
+
### 2. Преобразование потоков (Промежуточные операции)
|
|
77
|
+
Операции лениво объединяются в цепочку для определения конвейера.
|
|
259
78
|
```typescript
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
.toUnordered() // Преобразование в неупорядоченный коллектор
|
|
267
|
-
.toArray(); // Преобразование в массив
|
|
268
|
-
// Результат: [8, 12, 20]
|
|
269
|
-
|
|
270
|
-
// Пример сложной операции
|
|
271
|
-
const complexResult = range(1, 100, 1)
|
|
272
|
-
.flatMap(n => from([n, n * 2])) // Каждый элемент к двум
|
|
273
|
-
.distinct() // Удаление дубликатов
|
|
274
|
-
.shuffle() // Перемешивание порядка
|
|
275
|
-
.takeWhile(n => n < 50) // Взятие элементов меньше 50
|
|
276
|
-
.toOrdered() // Преобразование в упорядоченный коллектор
|
|
277
|
-
.toArray(); // Преобразование в массив
|
|
79
|
+
const processedStream = staticStream
|
|
80
|
+
.filter(x => x % 2 === 0) // Оставляем только четные числа
|
|
81
|
+
.map(x => x * 10) // Умножаем на 10
|
|
82
|
+
.flatMap(x => [x, x + 1]) // Преобразуем каждый элемент в два
|
|
83
|
+
.distinct(); // Удаляем дубликаты
|
|
84
|
+
// Пока ничего не было выполнено
|
|
278
85
|
```
|
|
279
86
|
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
| Метод | Описание | Временная сложность | Пространственная сложность |
|
|
283
|
-
|------------|------------|------------|------------|
|
|
284
|
-
| `sorted()` | Преобразование в упорядоченный коллектор | O(n log n) | O(n) |
|
|
285
|
-
| `toUnordered()` | Преобразование в неупорядоченный коллектор | O(1) | O(1) |
|
|
286
|
-
| `toOrdered()` | Преобразование в упорядоченный коллектор | O(1) | O(1) |
|
|
287
|
-
| `toNumericStatistics()` | Преобразование в числовую статистику | O(n) | O(1) |
|
|
288
|
-
| `toBigintStatistics()` | Преобразование в статистику BigInt | O(n) | O(1) |
|
|
289
|
-
| `toWindow()` | Преобразование в оконный коллектор | O(1) | O(1) |
|
|
290
|
-
| `toCollectable()` | Преобразование в UnorderdCollectable | O(n) | O(1) |
|
|
291
|
-
| `toCollectable(mapper)` | Преобразование в настраиваемый коллектор | O(n) | O(1) |
|
|
292
|
-
|
|
87
|
+
### 3. Выполнение потоков (Терминальные операции)
|
|
88
|
+
Чтобы получить результат, вы должны получить Collectable и вызвать терминальную операцию.
|
|
293
89
|
```typescript
|
|
294
|
-
//
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
from([6, 4, 3, 5, 2]) // Создание потока
|
|
309
|
-
.redirect((element, index) => -index) // Перенаправление в обратном порядке
|
|
310
|
-
.toUnorderd() // Игнорирование перенаправления. Эта операция игнорирует `redirect`, `reverse`, `shuffle` и `translate`
|
|
311
|
-
.toArray(); // [2, 5, 3, 4, 6]
|
|
312
|
-
|
|
313
|
-
from([6, 4, 3, 5, 2]) // Создание потока
|
|
314
|
-
.reverse() // Обращение потока
|
|
315
|
-
.toOrdered() // Гарантия обращенного порядка
|
|
316
|
-
.toArray(); // [2, 5, 3, 4, 6]
|
|
317
|
-
|
|
318
|
-
from([6, 4, 3, 5, 2]) // Создание потока
|
|
319
|
-
.shuffle() // Перемешивание потока
|
|
320
|
-
.sorted() // Перезапись перемешанного порядка. Эта операция перезапишет `redirect`, `reverse`, `shuffle` и `translate`
|
|
321
|
-
.toArray(); // [2, 5, 3, 4, 6]
|
|
322
|
-
|
|
323
|
-
from([6, 4, 3, 5, 2]) // Создание потока
|
|
324
|
-
.toWindow(); // Преобразование в оконный коллектор
|
|
325
|
-
|
|
326
|
-
from([6, 4, 3, 5, 2]) // Создание потока
|
|
327
|
-
.toNumericStatistics(); // Преобразование в числовую статистику
|
|
328
|
-
|
|
329
|
-
from([6n, 4n, 3n, 5n, 2n]) // Создание потока
|
|
330
|
-
.toBigintStatistics(); // Преобразование в статистику BigInt
|
|
331
|
-
|
|
332
|
-
// Определение настраиваемого коллектора для сбора данных
|
|
333
|
-
let customizedCollector = from([1, 2, 3, 4, 5])
|
|
334
|
-
.toCollectable((generator: Generator<E>) => new CustomizedCollector(generator));
|
|
90
|
+
// Получаем неупорядоченный collectable для производительности
|
|
91
|
+
const resultArray = await processedStream.toUnordered().toArray();
|
|
92
|
+
console.log(resultArray); // например, [20, 21, 40, 41]
|
|
93
|
+
|
|
94
|
+
// Используем встроенный коллектор
|
|
95
|
+
const sum = await processedStream.toUnordered().collect(useSummate());
|
|
96
|
+
console.log(sum);
|
|
97
|
+
|
|
98
|
+
// Или используем общий метод collect
|
|
99
|
+
const customResult = await processedStream.toOrdered().collect(
|
|
100
|
+
() => new Map<number, number>(),
|
|
101
|
+
(map, element, index) => map.set(index, element),
|
|
102
|
+
map => map
|
|
103
|
+
);
|
|
335
104
|
```
|
|
336
105
|
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
| Метод | Описание | Временная сложность | Пространственная сложность |
|
|
340
|
-
|------|------|------------|------------|
|
|
341
|
-
| `anyMatch(predicate)` | Соответствие любого элемента | O(n) | O(1) |
|
|
342
|
-
| `allMatch(predicate)` | Соответствие всех элементов | O(n) | O(1) |
|
|
343
|
-
| `count()` | Подсчет элементов | O(n) | O(1) |
|
|
344
|
-
| `isEmpty()` | Проверка на пустоту | O(1) | O(1) |
|
|
345
|
-
| `findAny()` | Найти любой элемент | O(n) | O(1) |
|
|
346
|
-
| `findFirst()` | Найти первый элемент | O(n) | O(1) |
|
|
347
|
-
| `findLast()` | Найти последний элемент | O(n) | O(1) |
|
|
348
|
-
| `forEach(action)` | Итерация по всем элементам | O(n) | O(1) |
|
|
349
|
-
| `group(classifier)` | Группировка по классификатору | O(n) | O(n) |
|
|
350
|
-
| `groupBy(keyExtractor, valueExtractor)` | Группировка по ключу-значению | O(n) | O(n) |
|
|
351
|
-
| `join()` | Объединение в строку | O(n) | O(n) |
|
|
352
|
-
| `join(delimiter)` | Объединение с использованием разделителя | O(n) | O(n) |
|
|
353
|
-
| `nonMatch(predicate)` | Отсутствие соответствия элементов | O(n) | O(1) |
|
|
354
|
-
| `partition(count)` | Разделение по количеству | O(n) | O(n) |
|
|
355
|
-
| `partitionBy(classifier)` | Разделение по классификатору | O(n) | O(n) |
|
|
356
|
-
| `reduce(accumulator)` | Операция уменьшения | O(n) | O(1) |
|
|
357
|
-
| `reduce(identity, accumulator)` | Уменьшение с начальным значением | O(n) | O(1) |
|
|
358
|
-
| `toArray()` | Преобразование в массив | O(n) | O(n) |
|
|
359
|
-
| `toMap(keyExtractor, valueExtractor)` | Преобразование в карту | O(n) | O(n) |
|
|
360
|
-
| `toSet()` | Преобразование в множество | O(n) | O(n) |
|
|
361
|
-
| `write(stream)` | Запись в поток | O(n) | O(1) |
|
|
362
|
-
|
|
106
|
+
### 4. Важно: Работа с потоками событий
|
|
107
|
+
Потоки событий (useDocument, useWindow, useHTMLElement, useWebSocket) по своей природе бесконечны. Вы должны использовать операции, такие как sub, takeWhile или limit, чтобы определить, когда прекратить сбор событий и завершить поток. В противном случае терминальная операция будет ждать неопределенно долго.
|
|
363
108
|
```typescript
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
//
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
// Операции вывода
|
|
384
|
-
data.join(", "); // "[2, 4, 6, 8, 10]"
|
|
109
|
+
import { useDocument } from 'semantic-typescript';
|
|
110
|
+
|
|
111
|
+
// Собираем только первые 5 кликов
|
|
112
|
+
const first5Clicks = await useDocument('click')
|
|
113
|
+
.limit(5) // <- Важно: ограничивает поток 5 событиями
|
|
114
|
+
.toUnordered()
|
|
115
|
+
.toArray();
|
|
116
|
+
|
|
117
|
+
// Собираем клики в течение 10-секундного окна
|
|
118
|
+
const clicksIn10s = await useDocument('click')
|
|
119
|
+
.takeWhile((_, index, startTime = Date.now()) => Date.now() - startTime < 10000)
|
|
120
|
+
.toUnordered()
|
|
121
|
+
.toArray();
|
|
122
|
+
|
|
123
|
+
// Собираем клики с индекса 2 по 5 (0-based)
|
|
124
|
+
const specificClicks = await useDocument('click')
|
|
125
|
+
.sub(2n, 6n) // <- Берет элементы с индексами 2, 3, 4, 5
|
|
126
|
+
.toUnordered()
|
|
127
|
+
.toArray();
|
|
385
128
|
```
|
|
129
|
+
**Ключевое понимание**: Событие (например, MouseEvent) и его порядковый индекс срабатывания (в виде bigint) передаются вместе через конвейер с помощью обратного вызова `accept(event, index)`.
|
|
386
130
|
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
### Методы NumericStatistics
|
|
390
|
-
|
|
391
|
-
| Метод | Описание | Временная сложность | Пространственная сложность |
|
|
392
|
-
|------|------|------------|------------|
|
|
393
|
-
| `range()` | Диапазон | O(n) | O(1) |
|
|
394
|
-
| `variance()` | Дисперсия | O(n) | O(1) |
|
|
395
|
-
| `standardDeviation()` | Стандартное отклонение | O(n) | O(1) |
|
|
396
|
-
| `mean()` | Среднее значение | O(n) | O(1) |
|
|
397
|
-
| `median()` | Медиана | O(n log n) | O(n) |
|
|
398
|
-
| `mode()` | Мода | O(n) | O(n) |
|
|
399
|
-
| `frequency()` | Распределение частот | O(n) | O(n) |
|
|
400
|
-
| `summate()` | Суммирование | O(n) | O(1) |
|
|
401
|
-
| `quantile(quantile)` | Квантиль | O(n log n) | O(n) |
|
|
402
|
-
| `interquartileRange()` | Межквартильный размах | O(n log n) | O(n) |
|
|
403
|
-
| `skewness()` | Асимметрия | O(n) | O(1) |
|
|
404
|
-
| `kurtosis()` | Эксцесс | O(n) | O(1) |
|
|
405
|
-
|
|
131
|
+
### 5. Использование статистики
|
|
406
132
|
```typescript
|
|
407
|
-
|
|
408
|
-
const numbers = from([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
|
|
409
|
-
.toNumericStatistics();
|
|
410
|
-
|
|
411
|
-
console.log("Среднее:", numbers.mean()); // 5.5
|
|
412
|
-
console.log("Медиана:", numbers.median()); // 5.5
|
|
413
|
-
console.log("Стандартное отклонение:", numbers.standardDeviation()); // ~2.87
|
|
414
|
-
console.log("Сумма:", numbers.summate()); // 55
|
|
415
|
-
|
|
416
|
-
// Статистический анализ с использованием мапперов
|
|
417
|
-
const objects = from([
|
|
418
|
-
{ value: 10 },
|
|
419
|
-
{ value: 20 },
|
|
420
|
-
{ value: 30 }
|
|
421
|
-
]).toNumericStatistics();
|
|
422
|
-
console.log("Преобразованное среднее:", objects.mean(obj => obj.value)); // 20
|
|
423
|
-
```
|
|
133
|
+
const numericStream = useFrom([10, 20, 30, 40, 50]).toNumeric();
|
|
424
134
|
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
// Когда не требуется гарантия порядка, используйте неупорядоченный коллектор для лучшей производительности
|
|
430
|
-
let highPerformance = data
|
|
431
|
-
.filter(predicate)
|
|
432
|
-
.map(mapper)
|
|
433
|
-
.toUnordered(); // Лучшая производительность
|
|
434
|
-
```
|
|
135
|
+
const average = await numericStream.average();
|
|
136
|
+
const median = await numericStream.median();
|
|
137
|
+
const standardDeviation = await numericStream.standardDeviation();
|
|
138
|
+
const skewness = await numericStream.skewness();
|
|
435
139
|
|
|
436
|
-
|
|
437
|
-
```typescript
|
|
438
|
-
// Когда необходимо сохранить порядок элементов, используйте упорядоченный коллектор
|
|
439
|
-
let ordered = data.sorted(comparator);
|
|
140
|
+
console.log(`Среднее: ${average}, Медиана: ${median}, Стандартное отклонение: ${standardDeviation}`);
|
|
440
141
|
```
|
|
441
142
|
|
|
442
|
-
|
|
143
|
+
## Основные возможности
|
|
144
|
+
* **Двойные типы потоков**: Полная поддержка как SynchronousSemantic (для Iterable), так и AsynchronousSemantic (для AsyncIterable и событий)
|
|
145
|
+
* **Богатый набор операций**: filter, map, flatMap, concat, distinct, sorted, limit, skip, peek, reverse, shuffle
|
|
146
|
+
* **Гибкие терминальные операции**: collect (с пользовательскими коллекторами), toArray, toSet, toMap, forEach, reduce, findFirst, anyMatch, allMatch, count
|
|
147
|
+
* **Продвинутые коллекторы**: Встроенные коллекторы для joining, groupingBy, partitioningBy, summing, averaging, maxBy, minBy
|
|
148
|
+
* **Статистический модуль**: Готовые к использованию методы для mean, median, mode, variance, standardDeviation, range, quantiles, skewness, kurtosis для числовых/bigint потоков
|
|
149
|
+
* **Вспомогательные функции**: Защитники типов (type guards) (isPromise, isAsyncIterable), компараторы (useCompare), обход (useTraverse) и хуки преобразования
|
|
150
|
+
* **Optional<T>**: Монадический контейнер для нулабельных значений, интегрированный с операциями поиска (find)
|
|
151
|
+
|
|
152
|
+
## Обзор API
|
|
153
|
+
### Основные классы и интерфейсы
|
|
154
|
+
* `Semantic<E>` / `AsynchronousSemantic<E>`: Абстрактное определение потока
|
|
155
|
+
* `Collectable<E>` / `AsynchronousCollectable<E>`: Исполняемый поток с терминальными операциями
|
|
156
|
+
* `OrderedCollectable<E>` / `UnorderedCollectable<E>`: Материализованные версии, оптимизированные для операций, чувствительных или нечувствительных к порядку
|
|
157
|
+
* `Collector<E, A, R>`: Абстракция для изменяемых (mutable) операций свёртки (reduction)
|
|
158
|
+
|
|
159
|
+
### Фабричные функции (use*)
|
|
160
|
+
* **Из источников**: useFrom, useRange, useFill, useEmpty
|
|
161
|
+
* **Из времени**: useInterval, useAnimationFrame
|
|
162
|
+
* **Из веб-API**: useBlob, useDocument, useWindow, useHTMLElement, useWebSocket
|
|
163
|
+
* **Коллекторы**: useToArray, useGroupBy, useSummate, useJoin и т.д.
|
|
164
|
+
|
|
165
|
+
## Примечания по производительности
|
|
166
|
+
* **Отложенное выполнение (Lazy Evaluation)**: Конвейеры составляются без выполнения до тех пор, пока не будет вызвана терминальная операция.
|
|
167
|
+
* **Короткое замыкание (Short-Circuiting)**: Операции, такие как limit, anyMatch и findFirst, остановят обработку элементов, как только результат будет определен.
|
|
168
|
+
* **Упорядоченное (Ordered) vs Неупорядоченное (Unordered)**:
|
|
169
|
+
* Используйте `.toUnordered()` для терминальных операций, когда порядок исходных элементов не имеет значения для вашего результата (например, для sum, max или toSet). Это может позволить внутренние оптимизации, пропускающие затратные шаги сортировки.
|
|
170
|
+
* Используйте `.toOrdered()`, когда важна последовательность (например, для toArray, где порядок должен быть сохранен).
|
|
171
|
+
|
|
172
|
+
## Пример для начала работы
|
|
443
173
|
```typescript
|
|
444
|
-
|
|
445
|
-
let windowed: WindowCollectable<number> = data
|
|
446
|
-
.toWindow()
|
|
447
|
-
.slide(5n, 2n); // Скользящее окно
|
|
448
|
-
```
|
|
174
|
+
import { useFrom, useSummate, useGroupBy } from 'semantic-typescript';
|
|
449
175
|
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
176
|
+
interface Transaction {
|
|
177
|
+
id: number;
|
|
178
|
+
amount: number;
|
|
179
|
+
category: string;
|
|
180
|
+
}
|
|
455
181
|
|
|
456
|
-
|
|
457
|
-
|
|
182
|
+
const transactions: Transaction[] = [
|
|
183
|
+
{ id: 1, amount: 100, category: 'Food' },
|
|
184
|
+
{ id: 2, amount: 200, category: 'Electronics' },
|
|
185
|
+
{ id: 3, amount: 50, category: 'Food' },
|
|
186
|
+
{ id: 4, amount: 300, category: 'Electronics' },
|
|
187
|
+
];
|
|
188
|
+
|
|
189
|
+
// Вычисляем общую сумму по категориям
|
|
190
|
+
const totalsByCategory = await useFrom(transactions)
|
|
191
|
+
.toUnordered()
|
|
192
|
+
.collect(
|
|
193
|
+
useGroupBy(
|
|
194
|
+
t => t.category,
|
|
195
|
+
t => t.amount,
|
|
196
|
+
useSummate() // Коллектор для значений
|
|
197
|
+
)
|
|
198
|
+
);
|
|
199
|
+
|
|
200
|
+
console.log(totalsByCategory); // Map { 'Food' => 150, 'Electronics' => 500 }
|
|
458
201
|
```
|
|
459
202
|
|
|
460
|
-
|
|
461
|
-
[NPMJS](https://www.npmjs.com/package/semantic-typescript)
|
|
462
|
-
|
|
463
|
-
## Важные замечания
|
|
464
|
-
|
|
465
|
-
1. **Влияние операций сортировки**: В упорядоченных коллекторах операция `sorted()` переопределяет эффекты `redirect`, `translate`, `shuffle`, `reverse`.
|
|
466
|
-
2. **Рассмотрение производительности**: Если не требуется гарантия порядка, предпочтение следует отдавать использованию `toUnordered()` для улучшения производительности.
|
|
467
|
-
3. **Использование памяти**: Операции сортировки требуют дополнительного пространства O(n).
|
|
468
|
-
4. **Реальное время**: Потоки Semantic подходят для обработки данных в реальном времени и поддерживают асинхронные источники данных.
|
|
203
|
+
Semantic-TypeScript создан для разработчиков, которые ищут тщательно спроектированную, типобезопасную и высокопроизводительную библиотеку для потоковой обработки данных. Он привносит мощь шаблонов преобразования данных уровня предприятия в экосистему TypeScript, идеально подходящую для насыщенных данными фронтенд-приложений, обработки данных в Node.js и любого сценария, где требуется элегантная и эффективная обработка последовательностей.
|
|
469
204
|
|
|
470
|
-
|
|
205
|
+
[](https://github.com/eloyhere/semantic-typescript) [](https://www.npmjs.com/package/semantic-typescript)
|