diff --git a/.claude/base/slot-plan.md b/.claude/base/slot-plan.md index 85f0fc7..3edd242 100644 --- a/.claude/base/slot-plan.md +++ b/.claude/base/slot-plan.md @@ -376,13 +376,19 @@ Remove/Extract/Move하려 해도 참조를 안 들고 있는 경우가 잦음. ` `Slot:Add`가 이미 받는 `State`/nested `Slot` 요소로 흡수 가능 (Slot-in-Slot, 위 "반응형 raw 요소"/"Slot-in-Slot 중첩" 절) — `Splice` 자체가 동적 배치를 떠받칠 이유가 없음. (2) **`T | {T}`가 여기선 오히려 - 틀림** — `Tag`의 `T`는 항상 plain `string`이라 `type(v) == "table"` - 분기가 "배열이냐 아니냐"를 안전하게 구분하지만, `Slot`의 `T`(`Instance - | Slot`)는 `Slot` 자신이 이미 테이블이라 "단일 `T`(마침 - 테이블인)"와 "`{T}` 배열"을 구분할 방법이 없음 — 억지로 하려면 - 결국 항상 명시적으로 감싸거나 풀어야 해서 vararg 대비 얻는 게 없음. - 이미 `{T}` 배열을 들고 있는 호출부는 `Splice(i, n, table.unpack(list))`로 - 충분(리스트가 하나뿐이라 tail-position 제약에도 안 걸림). + 틀림 — 이유는 "`Slot`의 `T`가 우연히 테이블(`Instance | Slot`) + 이라서"가 아니라, `Slot`가 base 레벨에선 `T`가 뭔지 전혀 모르는 + 제네릭이기 때문(다른 백엔드면 테이블일 수도, userdata일 수도, 그 밖에 + 뭐든 될 수 있음)** — `Tag`는 `T=string`으로 항상 고정·확정돼 있어 + `type(v) == "table"` 분기가 "배열이냐 아니냐"를 안전하게 구분하지만, + `Splice(idx, len, {item1, item2})`의 `{}`가 "그 자체로 하나의 `T` + 값(마침 테이블로 표현된)"인지 "펼쳐야 할 `{T}` 배열"인지는 `T`가 뭔지 + base가 애초에 모르므로 원천적으로 판별 불가능(quad-roblox에서 `T`에 + `Slot`이 섞여있는 건 이 문제를 드러내는 한 사례일 뿐, 근본 원인이 + 아님). 억지로 하려면 결국 항상 명시적으로 감싸거나 풀어야 해서 vararg + 대비 얻는 게 없음. 이미 `{T}` 배열을 들고 있는 호출부는 + `Splice(i, n, table.unpack(list))`로 충분(리스트가 하나뿐이라 + tail-position 제약에도 안 걸림). - **`Get`/`IndexOf` 신설, 원래 "YAGNI"로 뺐던 것을 재추가.** 처음엔 "`:List`가 자기 key→element 맵을 따로 들고 있어 Slot 내부 상태 조회가 불필요"하다고 판단해 드롭했으나, 위 인덱스 기준 전환과 맞물려 다시 diff --git a/.claude/session/2026-08-12-15-slot-in-slot-relate-scope-tag-splice-additions.md b/.claude/session/2026-08-12-15-slot-in-slot-relate-scope-tag-splice-additions.md index 8c81693..923a773 100644 --- a/.claude/session/2026-08-12-15-slot-in-slot-relate-scope-tag-splice-additions.md +++ b/.claude/session/2026-08-12-15-slot-in-slot-relate-scope-tag-splice-additions.md @@ -54,7 +54,13 @@ `newElements`에도 적용되는지 검토했으나 **기각, vararg 유지** — (1) 한 번에 갈아끼우는 요소 수는 호출부가 아는 소수인 경우가 대부분이고 정말 동적이면 Slot-in-Slot으로 흡수 가능해 `Splice` 자체가 그 케이스를 -떠받칠 이유가 없음, (2) `T | {T}`는 `Slot`의 `T`(`Instance | Slot`)가 -이미 테이블이라 "단일 T(마침 테이블)"와 "{T} 배열"을 구분 못 해 오히려 -틀림 — `Tag`의 `T=string`(항상 non-table)이라 안전했던 것과 다름 -(`slot-plan.md`에 반영). +떠받칠 이유가 없음, (2) `T | {T}`는 오히려 틀림 — **처음엔 이 이유를 +"`Slot`의 `T`(`Instance | Slot`)가 이미 테이블이라서"로 적었으나, 사용자가 +재지적: 진짜 이유는 `T`가 우연히 테이블을 포함해서가 아니라 `Slot`가 +base 레벨에선 `T`가 뭔지 전혀 모르는 제네릭이기 때문(다른 백엔드면 +테이블/userdata/그 밖에 뭐든 가능)** — 바깥 `{}`가 "그 자체로 하나의 +`T`(마침 테이블로 표현된)"인지 "펼쳐야 할 `{T}` 배열"인지 base가 `T`의 +정체를 모르므로 원천적으로 판별 불가능, quad-roblox의 `T`에 `Slot`이 +섞여있는 건 이 문제를 드러내는 한 사례일 뿐 근본 원인이 아님 — `Tag`의 +`T=string`(항상 고정·확정)이라 안전했던 것과 다름(`slot-plan.md`에 이 +정정으로 반영). diff --git a/CLAUDE.md b/CLAUDE.md index 045411e..a269704 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -642,5 +642,6 @@ vararg, `Slot:Splice` 신설** (`session/2026-08-12-15-slot-in-slot-relate-scope removeCount, ...newElements)` CRUD 신설 — 구간 제거+삽입을 shift/recompute 1회로 묶는 순수 최적화. `newElements`는 `Tag:Added`와 달리 의도적으로 vararg 유지(요소 개수가 대개 소수로 고정, 동적이면 Slot-in-Slot으로 흡수 -가능, `T|{T}`는 `Slot`의 `T` 자체가 테이블이라 오히려 모호해짐, -`slot-plan.md`). +가능, `T|{T}`는 `Slot`가 base 레벨에선 `T`가 뭔지 모르는 제네릭이라 +바깥 `{}`가 단일 T인지 배열인지 원천적으로 판별 불가능해서 오히려 +모호해짐 — `Slot`의 T에 우연히 Slot이 섞여서가 아님, `slot-plan.md`).