æ(?) — универсальный способ воспринимать
æ(thing)
æ(key, value)
æ(container, key, val)
æ.type(entity)
entity.æ
Реактивные производные — точечные обновления
Каждый метод возвращает новую æ-коллекцию. Мутация источника точечно обновляет результат — без полного пересчёта.
Array.map — трансформация
src = æ([1, 2, 3])
mapped = src.map(x => x * 10) → [10, 20, 30]
src.push(4) → mapped: [10, 20, 30, 40]
src.pop() → mapped: [10, 20, 30]
Array.filter — фильтрация
src = æ([1, 2, 3, 4, 5])
filtered = src.filter(x => x > 2) → [3, 4, 5]
src.push(6) → filtered: [3, 4, 5, 6]
src.push(1) → filtered: [3, 4, 5, 6]
Set.intersection — пересечение
a = æ(new Set([1, 2, 3, 4]))
b = æ(new Set([3, 4, 5, 6]))
inter = a.intersection(b) → {3, 4}
a.add(5) → inter: {3, 4, 5}
a.add(7) → inter: {3, 4, 5}
b.delete(3) → inter: {4, 5}
Set.difference — разность
a = æ(new Set([1, 2, 3, 4]))
b = æ(new Set([3, 4, 5]))
diff = a.difference(b) → {1, 2}
a.add(6) → diff: {1, 2, 6}
b.add(2) → diff: {1, 6}
b.delete(3) → diff: {1, 3, 6}
Map.mapValues — трансформация значений
m = æ(new Map([["a",1], ["b",2], ["c",3]]))
doubled = m.mapValues(v => v * 2) → {a:2, b:4, c:6}
m.set("d", 4) → doubled.get("d"): 8
m.set("a", 10) → doubled.get("a"): 20
m.delete("c") → doubled.has("c"): false
Map.filter — реактивная фильтрация
m = æ(new Map([["a",1], ["b",2], ["c",3], ["d",4]]))
big = m.filter(v => v > 2) → {c:3, d:4}
m.set("e", 5) → big: {c:3, d:4, e:5}
m.set("a", 10) → big: {a:10, c:3, d:4, e:5}
m.set("c", 0) → big: {a:10, d:4, e:5}
Цепочки производных
Производные можно строить от производных. Изменение корня пропагируется по всей цепочке.
users = æ(new Set(["alice", "bob", "charlie", "dave"]))
admins = æ(new Set(["alice", "charlie"]))
banned = æ(new Set(["dave"]))
allowed = users.difference(banned) → {alice, bob, charlie}
moderators = allowed.intersection(admins) → {alice, charlie}
banned.add("charlie"):
allowed → {alice, bob}
moderators → {alice}
Остановка — æ.destruct()
destruct() отсекает производное от источника. Каскадно уничтожает всю подветвь.
src = æ([1, 2, 3])
mapped = src.map(x => x * 10)
src.push(4) → mapped: [10, 20, 30, 40]
æ.destruct(mapped)
src.push(5) → mapped остановлен
src жив: [1, 2, 3, 4, 5]
Подписка на события
const s = æ(new Set([1, 2, 3]))
const handle = æ.On(s, e => console.log(e))
s.add(4) → {type: "set:add", content: "add", value: 4}
s.delete(2) → {type: "set:delete", content: "delete", value: 2}
s.add(4) → ничего — идемпотентно, 4 уже есть
æ.destruct(handle)
s.add(5)
CLI
npm i -g vaed-ai
vaed-ai
> æ
> æ({name: "Alice"})
> æ(user, "knows", other)
REPL с полным доступом к æ — интерактивное исследование графа