Source
Source는 값을 직접 쓸 수 있는 유일한 반응형 노드입니다. 파생 노드인 State는 읽기 전용이고, 전파는 언제나 어떤 Source의 :Set/:Emit에서 시작합니다.
이 페이지의 심볼: q.Source(value) · source:Set(v) · source:Emit() · source.Revision · Source가 물려받는 State 메소드
-- 설치 경로는 프로젝트 구성에 따라 다르다(00-installation 참고)local Quad = require(<quad-base 모듈 경로>)local QuadRoblox = require(<quad-roblox 모듈 경로>).QuadRobloxlocal QuadTypes = require(<quad-types 모듈 경로>) -- 타입 주석용(`QuadTypes.State<T>` 등)local q = Quad:UseProvider(QuadRoblox) -- quad-roblox 백엔드 설치: D/Tween/Animate/OnChange가 생긴다Source의 생성·읽기·쓰기와 :Compute/:With 같은 파생 자체는 백엔드가 없어도 동작합니다. 백엔드가 필요한 것은 이 노드에 붙는 구독 핸들의 생명주기입니다 — :Observer로 만든 핸들을 실제로 살리는 것(:Subscribe, 인스턴스 바인딩)부터가 백엔드 몫입니다(05-observer-effect 참고).
q.Source(value)
섹션 제목: “q.Source(value)”시그니처
Source: <T>(v: T) -> Source<T>
export type Source<T> = State<T> & { Revision: number, Set: (self: Source<T>, v: T) -> Source<T>, Emit: (self: Source<T>) -> Source<T>,}인자
| 이름 | 타입 | 설명 |
|---|---|---|
v |
T |
초기값. nil도 값으로 허용됩니다(q.Source(nil :: number?) — 타입은 명시해야 Source<number?>가 됩니다). |
반환 — Source<T>. 만들어진 시점의 Revision은 0입니다.
동작
- 값으로 Modifier는 담을 수 없습니다. 생성자에서 걸리면
Source: cannot hold a Modifier as a Source value - 판정 술어는 셋 다 참입니다 —
q.isSource(s),q.isEpoch(s),q.isState(s). 세 번째는 술어 합성의 결과이고, 값 자체가State브랜드에 등록되지는 않습니다. print(source)는Source(<현재 값>)모양으로 찍힙니다. 읽기만 하며 계산을 유발하지 않습니다.
예제
local hp = q.Source(100)print(hp:Get()) --> 100관련 — Getting Started 01 핵심 모델 · Quadnomicon Vol. 1
source:Set(v)
섹션 제목: “source:Set(v)”시그니처
Set: (self: Source<T>, v: T) -> Source<T>인자
| 이름 | 타입 | 설명 |
|---|---|---|
v |
T |
새 값. Modifier는 거부됩니다. |
반환 — self(체이닝 가능).
동작
- 같은 값을 다시 넣어도 언제나 리비전을 올리고 전파합니다. 값 비교로 중복을 죽이지 않습니다 — 중복 제거는 하류의 판단이고(에폭 판정·게이트),
==비교는 테이블을 제자리에서 고친 변경을 조용히 삼켜버리기 때문입니다. :Get()은 넣은 참조를 그대로 돌려줍니다(사본이 아닙니다). 테이블을 담아 두고 제자리에서 고쳤다면:Emit()으로 신호만 보내면 됩니다.- Modifier를 넣으면
Source: cannot Set a Modifier as a Source value
예제
local hp = q.Source(100)hp:Set(80):Set(60) -- self를 돌려주므로 이어 쓸 수 있다print(hp:Get()) --> 60source:Emit()
섹션 제목: “source:Emit()”시그니처
Emit: (self: Source<T>) -> Source<T>반환 — self.
동작
- 값은 건드리지 않고 리비전만 올려 하류에 전파합니다. 담아둔 테이블·배열을 제자리에서 고친 뒤 알릴 때 쓰는 문입니다.
- 루트
Source에만 있는 개념입니다. 파생State에는:Emit이 없습니다 — 파생 노드의 값은 자기 것이 아니기 때문입니다.
예제
local items = q.Source({ "a" })table.insert(items:Get(), "b") -- 제자리 변경 — 이것만으로는 아무도 모른다items:Emit() -- 이제 하류가 안다source.Revision
섹션 제목: “source.Revision”시그니처
Revision: number동작
:Set/:Emit이 일어날 때마다 바뀌는 불투명한 표식입니다. 하류는 “이 값을 마지막으로 본 뒤에 움직였는가”를 이 값의 일치/불일치로만 판정합니다.- 크고 작음을 비교하지 마세요 — 증가가 아니라
bit32랩어라운드로 감소하는 방향으로 갱신됩니다. 저장해 둔 값과 같으면 그 사이 아무 일도 없었다는 뜻, 다르면 움직였다는 뜻, 그게 전부입니다. - 갓 만든
Source의 값은0입니다.
관련 — Quadnomicon Vol. 1 — Revision과 EpochMap
Source가 물려받는 State 메소드
섹션 제목: “Source가 물려받는 State 메소드”Source는 타입으로도 런타임으로도 State를 포함합니다 — 파생 메소드는 별도 변환 없이 Source 위에서 바로 부를 수 있습니다.
| 메소드 | 문서 |
|---|---|
:Get() |
03-state |
:Compute(fn, ...deps) |
03-state |
:With(...) |
03-state |
:Apply(factory) |
03-state |
:Observer(fn) |
05-observer-effect |
:Gate(setup) |
03-state |
한 가지 예외는 :Get()입니다. Source는 자기 값을 그대로 돌려주는 자기만의 :Get()을 갖습니다(캐시도 재계산도 없습니다). 나머지는 State의 구현을 그대로 씁니다.
local hp = q.Source(100)local label: QuadTypes.State<string> = hp:Compute(function(self) return `HP {self:Get()}`end)관련 — 03-state · 04-store · How-To 02 폼 검증