Трансформация resolveReferences

Внутреннее разрешение ссылок (resolveReferences) в Vega и Vega-Lite представляет собой слой нормализации, который приводит разнородные описания данных, сигналов и вычисляемых выражений к единой системе адресации. Этот механизм играет критическую роль в момент компиляции спецификации, когда декларативное описание графика преобразуется в исполняемый план.

В основе лежит идея того, что любое имя поля, сигнала или вычисляемого выражения может существовать в нескольких контекстах: внутри трансформаций данных, внутри композиционных операторов (layer, facet, concat, repeat), а также в области сигналов (signals). resolveReferences отвечает за устранение неоднозначности и построение корректных связей между этими областями.


Контекстные области и природа ссылок

Каждая ссылка в Vega/Vega-Lite существует в одном из контекстов:

  • Data field reference — обращение к полям данных (datum.x, datum["x"])
  • Signal reference — обращение к динамическим параметрам (signalName)
  • Scale/axis reference — косвенные зависимости через шкалы и оси
  • Transform reference — поля, создаваемые вычислениями (calculate, aggregate, lookup)
  • Composition reference — ссылки между подграфиками (facet/layer/repeat)

resolveReferences выполняет унификацию этих контекстов, приводя их к внутреннему графу зависимостей.


Этапы разрешения ссылок

Процесс resolveReferences можно рассматривать как последовательность фаз компиляции.

1. Лексическая нормализация имен

На первом этапе выполняется приведение всех ссылок к каноническому виду:

  • алиасы полей заменяются на исходные имена
  • выражения вида datum["field"] преобразуются в единый формат доступа
  • сигналы приводятся к глобальному пространству имен

На этом уровне устраняется синтаксическая неоднозначность.


2. Разделение пространств имен

Vega/Vega-Lite использует строго разделенные области:

  • data namespace
  • signal namespace
  • scale namespace
  • component namespace (axes, legends, marks)

resolveReferences строит таблицы символов для каждой области, предотвращая коллизии имен. Например, поле данных color и сигнал color не конфликтуют, но требуют явного контекстного разрешения при использовании в выражениях.


3. Построение графа зависимостей

После нормализации формируется направленный ациклический граф зависимостей:

  • узлы — сигналы, данные, трансформации
  • ребра — ссылки между ними

Пример зависимости:

data -> transform -> scale -> mark encoding -> rendering
signal -> transform -> encoding

resolveReferences фиксирует порядок вычисления, гарантируя, что все зависимости вычисляются до их использования.


resolveReferences в трансформациях данных

Особенно важную роль механизм играет внутри цепочек трансформаций.

Lookup-трансформации

При использовании lookup происходит связывание двух наборов данных:

  • основной dataset
  • внешний dataset

resolveReferences выполняет:

  • сопоставление ключей
  • проверку существования полей
  • построение виртуальных join-ссылок

Результатом становится расширенная структура datum, где внешние поля доступны как локальные.


Aggregate и calculate

В агрегирующих трансформациях возникают новые поля, которые могут ссылаться на ранее вычисленные значения.

resolveReferences обеспечивает:

  • корректный порядок вычислений агрегатов
  • предотвращение циклических ссылок
  • приведение выражений к внутреннему AST (Abstract Syntax Tree)

Window-трансформации

Оконные функции создают зависимости между соседними строками данных. resolveReferences фиксирует:

  • порядок сортировки (если задан)
  • область окна
  • доступные поля внутри окна

resolveReferences в композиции визуализаций

В Vega-Lite композиционные операторы создают дополнительный уровень сложности.

Layer

В слоистых визуализациях каждый слой имеет собственное пространство данных и энкодингов. resolveReferences выполняет:

  • изоляцию слоев
  • разрешение общих сигналов
  • согласование шкал при shared/independent конфигурации

Особенно важно поведение при перекрытии имен шкал и полей.


Facet

Facet генерирует множество подграфиков на основе одного поля. resolveReferences:

  • создает подстановочные ссылки на группирующее поле
  • клонирует сигналы на уровень подграфика
  • строит индексированную структуру данных

Каждый facet становится независимым контекстом, но сохраняет связь с родительским dataset.


Repeat

При повторении визуализаций resolveReferences выполняет параметрическую подстановку:

  • шаблонные ссылки заменяются на конкретные поля
  • сигналы дублируются с суффиксами индексов
  • шкалы либо разделяются, либо переиспользуются в зависимости от конфигурации

resolveReferences и система сигналов

Сигналы представляют динамическое состояние спецификации. resolveReferences обеспечивает их корректную интеграцию в граф вычислений.

Подстановка сигналов в выражения

Любое выражение может содержать сигналы:

  • в transform
  • в encoding
  • в scale domain/range

resolveReferences заменяет символические имена сигналов на ссылки в runtime store.


Зависимости сигналов

Сигналы могут зависеть друг от друга, образуя граф:

  • простые зависимости: b = a + 1
  • каскадные зависимости: c = b * 2

resolveReferences гарантирует топологическую сортировку сигналов.


Конфликты и стратегии разрешения

В сложных спецификациях неизбежно возникают конфликты имен.

Конфликт полей и сигналов

Если поле данных и сигнал имеют одинаковое имя:

  • приоритет определяется контекстом выражения
  • в encoding предпочтение часто отдается данным
  • в signal expression — сигналам

resolveReferences явно маркирует происхождение каждой ссылки.


Конфликт шкал в композиции

В layer и facet возникает вопрос:

  • использовать общую шкалу
  • или независимые шкалы

resolveReferences применяет стратегию из блока resolve:

  • shared — объединение ссылок на одну шкалу
  • independent — генерация отдельных экземпляров

Внутреннее представление после resolveReferences

После завершения обработки спецификация превращается в нормализованный граф:

  • все ссылки заменены на идентификаторы узлов
  • выражения представлены в AST-форме
  • зависимости строго определены

Этот граф является входом для runtime Vega, где выполняется фактический рендеринг.


Оптимизация ссылочной структуры

resolveReferences также выполняет ряд оптимизаций:

  • устранение дублирующихся ссылок
  • кэширование выражений
  • сворачивание цепочек преобразований
  • инлайнинг простых сигналов

Эти операции уменьшают глубину графа и ускоряют последующее вычисление.


Связь с трансформационной моделью Vega

Вся система трансформаций Vega/Vega-Lite опирается на единый принцип: данные, сигналы и визуальные компоненты существуют как узлы одного графа. resolveReferences является механизмом, который превращает декларативные ссылки в этот граф, обеспечивая:

  • детерминированный порядок вычислений
  • изоляцию контекстов
  • корректную композицию визуализаций
  • согласованность между уровнями спецификации

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