[{"data":1,"prerenderedAt":554},["ShallowReactive",2],{"navigation_docs":3,"-design-adrs-007-one-value-sets":101,"-design-adrs-007-one-value-sets-surround":549},[4,23,66],{"title":5,"icon":6,"path":7,"stem":8,"children":9,"page":22},"Guide","i-lucide-book-open","\u002Fguide","1.guide",[10,14,18],{"title":11,"path":12,"stem":13},"Introduction","\u002Fguide\u002Fintroduction","1.guide\u002F1.introduction",{"title":15,"path":16,"stem":17},"Getting started","\u002Fguide\u002Fgetting-started","1.guide\u002F2.getting-started",{"title":19,"path":20,"stem":21},"Pieces and sets","\u002Fguide\u002Fpieces-and-sets","1.guide\u002F3.pieces-and-sets",false,{"title":24,"icon":25,"path":26,"stem":27,"children":28},"Design (ADRs)","i-lucide-drafting-compass","\u002Fdesign","2.design",[29,32],{"title":30,"path":26,"stem":31},"Design decisions (ADRs)","2.design\u002Findex",{"title":33,"icon":34,"path":35,"stem":36,"children":37,"page":22},"Decision records","i-lucide-scroll-text","\u002Fdesign\u002Fadrs","2.design\u002Fadrs",[38,42,46,50,54,58,62],{"title":39,"path":40,"stem":41},"ADR-001: The refinement-chain model for calendar points","\u002Fdesign\u002Fadrs\u002F001-refinement-chain","2.design\u002Fadrs\u002F001-refinement-chain",{"title":43,"path":44,"stem":45},"ADR-002: Sets first — the Span algebra","\u002Fdesign\u002Fadrs\u002F002-set-primary-spans","2.design\u002Fadrs\u002F002-set-primary-spans",{"title":47,"path":48,"stem":49},"ADR-003: Overflow policy — clamp by default, skip on request","\u002Fdesign\u002Fadrs\u002F003-overflow-policy","2.design\u002Fadrs\u002F003-overflow-policy",{"title":51,"path":52,"stem":53},"ADR-004: Fortnights as every-k scopes","\u002Fdesign\u002Fadrs\u002F004-fortnight-scopes","2.design\u002Fadrs\u002F004-fortnight-scopes",{"title":55,"path":56,"stem":57},"ADR-005: One denotation function, and what DST does to it","\u002Fdesign\u002Fadrs\u002F005-shared-denotation","2.design\u002Fadrs\u002F005-shared-denotation",{"title":59,"path":60,"stem":61},"ADR-006: Zocam is a standalone, released library","\u002Fdesign\u002Fadrs\u002F006-standalone-library","2.design\u002Fadrs\u002F006-standalone-library",{"title":63,"path":64,"stem":65},"ADR-007: A set is one value — struct answers, enumerable shapes","\u002Fdesign\u002Fadrs\u002F007-one-value-sets","2.design\u002Fadrs\u002F007-one-value-sets",{"title":67,"path":68,"stem":69,"children":70,"icon":100},"API Reference","\u002Fapi","3.api\u002Findex",[71,72,76,80,84,88,92,96],{"title":67,"path":68,"stem":69},{"title":73,"path":74,"stem":75},"Zocam","\u002Fapi\u002Fzocam","3.api\u002Fzocam",{"title":77,"path":78,"stem":79},"Zocam.Intervals","\u002Fapi\u002Fzocam-intervals","3.api\u002Fzocam-intervals",{"title":81,"path":82,"stem":83},"Zocam.ISO","\u002Fapi\u002Fzocam-iso","3.api\u002Fzocam-iso",{"title":85,"path":86,"stem":87},"Zocam.Point","\u002Fapi\u002Fzocam-point","3.api\u002Fzocam-point",{"title":89,"path":90,"stem":91},"Zocam.Point.ComposeError","\u002Fapi\u002Fzocam-point-composeerror","3.api\u002Fzocam-point-composeerror",{"title":93,"path":94,"stem":95},"Zocam.Span","\u002Fapi\u002Fzocam-span","3.api\u002Fzocam-span",{"title":97,"path":98,"stem":99},"Zocam.Span.Arc","\u002Fapi\u002Fzocam-span-arc","3.api\u002Fzocam-span-arc","i-lucide-braces",{"id":102,"title":63,"body":103,"description":542,"extension":543,"links":544,"meta":545,"navigation":546,"path":64,"seo":547,"stem":65,"__hash__":548},"docs\u002F2.design\u002Fadrs\u002F007-one-value-sets.md",{"type":104,"value":105,"toc":535},"minimark",[106,124,129,132,136,164,167,210,224,231,235,241,267,282,286,292,328,337,378,418,423,426,479,483,489,492,505,513,531],[107,108,109,115,116,123],"p",{},[110,111,114],"span",{"className":112},[113],"ai-slop","AI SLOP"," an AI agent wrote this page. ",[117,118,122],"a",{"href":119,"rel":120},"https:\u002F\u002Fgithub.com\u002Fyuri4n",[121],"nofollow","yuri4n",", a senior engineer, gave the direction and did the review. The review is human, thus errors can stay.",[125,126,128],"h2",{"id":127},"status","Status",[107,130,131],{},"Accepted, 2026-08-05, decided by the project owner. The accepted option was refuted once, earlier the same day. This record names the refutation and what removed it (see Options).",[125,133,135],{"id":134},"context","Context",[107,137,138,139,142,143,146,147,151,152,155,156,159,160,163],{},"The kernel ",[140,141,77],"code",{}," accepts three spellings of \"some intervals\": one bare map (a piece), a plain list of maps, and the ",[140,144,145],{},"%Zocam.Intervals{}"," struct. Before this decision, the set operations also ",[148,149,150],"em",{},"answered"," in three shapes. The documented rule said: \"the answer follows the shape of the first argument\". ",[140,153,154],{},"diff(piece, piece)"," answered with a piece or ",[140,157,158],{},"nil",". ",[140,161,162],{},"diff(list, list)"," answered with a list. Only the struct got the struct back.",[107,165,166],{},"An audit of the kernel (the decision issue YUR-55 on the project board) found three problems with that rule.",[168,169,170,182,196],"ul",{},[171,172,173,177,178,181],"li",{},[174,175,176],"strong",{},"The rule was false."," The dispatch looked at both arguments, not at the first one. ",[140,179,180],{},"diff(piece, list)"," answered with a list. The sentence in the docs and the code disagreed.",[171,183,184,187,188,191,192,195],{},[174,185,186],{},"The kernel did not follow its own rule."," ",[140,189,190],{},"union\u002F2"," took lists only and crashed on a piece or on the struct. ",[140,193,194],{},"overlaps?\u002F2"," answered with a boolean at every level. The rule had exceptions from the start.",[171,197,198,201,202,205,206,209],{},[174,199,200],{},"The dispatch made a defect possible."," A map with ",[140,203,204],{},"from"," and ",[140,207,208],{},"until"," but no closings passed the entry check (two keys) and failed the piece guard (four keys). The operation clauses passed it around in a circle, and the call never returned. This was the infinite loop of YUR-79. The multi-level dispatch was the ground it stood on.",[107,211,212,213,215,216,219,220,223],{},"The three answer shapes also spelled \"nothing remains\" three ways: ",[140,214,158],{}," at the piece level, ",[140,217,218],{},"[]"," at the list level, ",[140,221,222],{},"%Zocam.Intervals{intervals: []}"," at the struct level. Every caller had to know which empty value to expect.",[107,225,226,227,230],{},"One more force: ",[117,228,229],{"href":44},"ADR-002"," already made sets primary in the symbolic layer, for closure — an operation on a set can answer with more pieces than it received, so only a set type survives its own operators. The concrete kernel had the same closure need, but not the same answer.",[125,232,234],{"id":233},"options","Options",[107,236,237,240],{},[174,238,239],{},"Option A: keep the shape-following dispatch and repair it."," Fix the false sentence, and make the entry funnel raise on a partial map. Caveat: the three spellings of \"empty\" stay, every caller keeps a three-way case, and the piece-level dispatch — the ground the loop stood on — stays in the code.",[107,242,243,246,247,250,251,254,255,258,259,262,263,266],{},[174,244,245],{},"Option B: always answer with the struct."," One return shape for every set operation. This option was proposed in the audit and ",[174,248,249],{},"refuted"," there: the struct did not implement ",[140,252,253],{},"Enumerable"," at that time. The list answer was the only shape that ",[140,256,257],{},"Enum"," and comprehensions could walk, and the library itself used it that way — the evaluator inside ",[140,260,261],{},"Zocam.Span.ground\u002F3"," fed set-operation results to comprehension generators. Six call sites and one spec would break, and every walk over a result would first reach inside the struct for ",[140,264,265],{},".intervals",". Note what the refutation named: a missing capability of the struct, not a flaw in the idea.",[107,268,269,275,276,278,279,281],{},[174,270,271,272,274],{},"Option C: Option B plus ",[140,273,253],{},"."," Give the struct the capability whose absence refuted Option B. When ",[140,277,145],{}," enumerates its own pieces, a comprehension generator takes the struct directly, and the cost that killed Option B is gone. The same move applies to the other value that holds pieces: ",[140,280,97],{},", whose one instance is a row of grain cells.",[125,283,285],{"id":284},"decision","Decision",[107,287,288,289],{},"Option C is the chosen one. Two rules carry it, and one idea carries both: ",[174,290,291],{},"a set is one value.",[107,293,294,187,297,299,300,299,303,299,306,309,310,313,314,316,317,320,321,324,325,327],{},[174,295,296],{},"Rule one: an operation on sets answers with a set; a constructor of a piece answers with a piece.",[140,298,190],{},", ",[140,301,302],{},"intersect\u002F2",[140,304,305],{},"diff\u002F2",[140,307,308],{},"complement\u002F1",", and ",[140,311,312],{},"compress\u002F1"," accept every spelling — a piece, a list of pieces, or the struct — and always answer with ",[140,315,145],{},". One entry funnel normalizes every operand; a shape it cannot take raises an ",[140,318,319],{},"ArgumentError"," that names the rejected shape, so the partial-map loop of YUR-79 cannot start. ",[140,322,323],{},"new!\u002F1"," still builds one interval map, and ",[140,326,194],{}," still answers a boolean — neither is an operation on sets.",[107,329,330,333,334,336],{},[174,331,332],{},"Rule two: a value that holds pieces can be walked."," Both piece-holding values implement ",[140,335,253],{},", and each yields what it honestly holds:",[168,338,339,348],{},[171,340,341,343,344,347],{},[140,342,145],{}," yields its concrete ",[140,345,346],{},"interval()"," pieces, in normal-form order. Walk a grounded span and read fields off real windows.",[171,349,350,352,353,356,357,360,361,364,365,368,369,372,373,375,376,274],{},[140,351,97],{}," yields the symbolic cells of ",[174,354,355],{},"one instance",": ",[140,358,359],{},"Fri..Mon"," yields four weekday cells, ",[140,362,363],{},"Nov..Feb"," walks through the cycle seam, an ",[140,366,367],{},":open"," side drops that bound's cell, and a step on the grain unit samples every n-th cell. When one instance has no fixed cell row — a continuous ",[140,370,371],{},":time"," arc without a step, or a step that samples across instances (\"the 31st, monthly\") — ",[140,374,257],{}," raises an error that names the ways out: give the arc a step, or ground the span with ",[140,377,261],{},[379,380,385],"pre",{"className":381,"code":382,"language":383,"meta":384,"style":384},"language-mermaid shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","graph TD\n  SET[\"%Zocam.Intervals{}\u003Cbr\u002F>a concrete set\"] -->|\"Enum\"| P[\"its interval() pieces,\u003Cbr\u002F>in normal-form order\"]\n  ARC[\"Zocam.Span.Arc\u003Cbr\u002F>one symbolic piece\"] -->|\"Enum\"| C[\"the grain cells of\u003Cbr\u002F>one instance\"]\n  SPAN[\"Zocam.Span.t\u003Cbr\u002F>a symbolic set\"] -->|\"ground\u002F3\"| SET\n  SPAN -->|\"stream\u002F3\"| O[\"concrete occurrences,\u003Cbr\u002F>lazily, over real time\"]\n","mermaid","",[140,386,387,394,400,406,412],{"__ignoreMap":384},[110,388,391],{"class":389,"line":390},"line",1,[110,392,393],{},"graph TD\n",[110,395,397],{"class":389,"line":396},2,[110,398,399],{},"  SET[\"%Zocam.Intervals{}\u003Cbr\u002F>a concrete set\"] -->|\"Enum\"| P[\"its interval() pieces,\u003Cbr\u002F>in normal-form order\"]\n",[110,401,403],{"class":389,"line":402},3,[110,404,405],{},"  ARC[\"Zocam.Span.Arc\u003Cbr\u002F>one symbolic piece\"] -->|\"Enum\"| C[\"the grain cells of\u003Cbr\u002F>one instance\"]\n",[110,407,409],{"class":389,"line":408},4,[110,410,411],{},"  SPAN[\"Zocam.Span.t\u003Cbr\u002F>a symbolic set\"] -->|\"ground\u002F3\"| SET\n",[110,413,415],{"class":389,"line":414},5,[110,416,417],{},"  SPAN -->|\"stream\u002F3\"| O[\"concrete occurrences,\u003Cbr\u002F>lazily, over real time\"]\n",[107,419,420],{},[148,421,422],{},"Figure 1 — What a walk yields on each shape: concrete pieces from a set, symbolic cells from an arc, occurrences from a streamed span. AI generated, human reviewed.",[107,424,425],{},"The precise rules:",[168,427,428,448,467],{},[171,429,430,433,434,436,437,439,440,442,443,445,446,274],{},[174,431,432],{},"The empty set is one value."," \"Nothing remains\" is always ",[140,435,222],{}," — never ",[140,438,158],{},", never ",[140,441,218],{},". The bare literal ",[140,444,145],{}," is that same value, because the struct's list now defaults to ",[140,447,218],{},[171,449,450,457,458,461,462,205,465,274],{},[174,451,452,453,456],{},"The arc walk reuses ",[140,454,455],{},"ground\u002F3","'s reading of \"cell\"."," The same wrap rule, the same whole-unit closings, the same step sampling. One meaning of \"cell\", two interpreters — the same single-source rule that ",[117,459,460],{"href":56},"ADR-005"," set for ",[140,463,464],{},"member?\u002F2",[140,466,455],{},[171,468,469,475,476,274],{},[174,470,471,474],{},[140,472,473],{},"Enum.member?\u002F2"," is piece membership, not coverage."," It asks \"is this value one of the pieces?\", not \"is this instant inside the set?\". An instant inside a piece is still not a piece. For coverage, keep the span and ask ",[140,477,478],{},"Zocam.Span.member?\u002F2",[125,480,482],{"id":481},"consequences","Consequences",[107,484,485,486,488],{},"Easy now: composition. A set-operation result feeds the next operation, a comprehension, or ",[140,487,257],{},", with no shape check between. Callers stopped handling nil-or-list-or-struct, and the false \"first argument\" sentence is gone from every page.",[107,490,491],{},"This is a breaking change to the kernel's answers. The project has no users, so there is no deprecation path — the call sites, the tests, and the docs moved in the same change.",[107,493,494,495,498,499,501,502,504],{},"Hard now: the piece-level answers are gone. A caller that wants the bare list reaches for the ",[140,496,497],{},"intervals"," field. And ",[140,500,473],{}," looks like a coverage test to a newcomer but is not one; the pitfall is documented with a doctest in the ",[140,503,77],{}," moduledoc.",[107,506,507,508,205,510,512],{},"Open items: none in the code — the rules above are implemented and the tests pin them. The doctests in the ",[140,509,77],{},[140,511,97],{}," docs run in the test suite, so each example on this page's linked references stays true.",[514,515,516],"blockquote",{},[107,517,518,519,205,525,530],{},"See ",[117,520,521,522,524],{"href":78},"the ",[140,523,77],{}," module reference",[117,526,521,527,529],{"href":98},[140,528,97],{}," reference"," for the full rules with runnable examples.",[532,533,534],"style",{},"html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":384,"searchDepth":396,"depth":396,"links":536},[537,538,539,540,541],{"id":127,"depth":396,"text":128},{"id":134,"depth":396,"text":135},{"id":233,"depth":396,"text":234},{"id":284,"depth":396,"text":285},{"id":481,"depth":396,"text":482},"Accepted, 2026-08-05, decided by the project owner.","md",null,{},true,{"title":63,"description":542},"NRqfkLR8NwKr9PxN-Z01vtk8oJF6-qFeq0wGmItNbY0",[550,552],{"title":59,"path":60,"stem":61,"description":551,"children":-1},"Accepted, 2026-08-04, decided by the project owner (\"separate it as a library\"). Revised 2026-08-05: the chosen shape is now a separate repository that publishes to Hex.",{"title":67,"path":68,"stem":69,"description":553,"children":-1},"All public modules of zocam, generated from the Elixir docstrings by mix docs.",1786065169547]