feat(nanoviews): add match_ for a cascade of conditions - #219
Merged
Conversation
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #219 +/- ##
==========================================
+ Coverage 85.35% 85.40% +0.05%
==========================================
Files 140 142 +2
Lines 3155 3180 +25
Branches 594 595 +1
==========================================
+ Hits 2693 2716 +23
- Misses 332 335 +3
+ Partials 130 129 -1 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
A screen that waits, then fails, then has something to show is three conditions deep, and `if_` nests to say it: the third branch reads at the bottom of a staircase built out of the two before it.
`match_` takes the cascade as a list. The first case whose value is truthy renders, `default_` answers when none do, and a case is written with `when_`, which hands its own value to the branch the way `if_` does - as a signal, narrowed, so a change inside the branch updates the text and leaves the branch standing.
```
match_(
when_($loading, () => i()('Loading')),
when_($error, $error => b()($error)),
when_($post, $post => article()($post.$title)),
default_(() => 'Nothing to show')
)
```
The block reads the cases in order and stops at the one that holds, so it subscribes to the values above the winner and no further: a case below it is never asked, and never wakes the block when it changes.
dangreen
force-pushed
the
feat/nanoviews-match
branch
from
August 26, 2026 14:14
2a84e11 to
0927124
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
A screen that waits, then fails, then has something to show is three conditions deep, and
if_nests to say it:The last branch reads at the bottom of a staircase built out of the two before it, and adding a fourth state moves everything.
match_takes the same cascade as a list:The first case whose value is truthy renders;
default_answers when none do and may stand anywhere in the list.What
when_hands the branchThe branch gets the case's signal, narrowed through
TruthySignalish— the same contractif_gives itsthen_. Not the value: a branch that took the value would depend on it, and every change inside would rebuild the whole subtree instead of updating the text node that changed. There is a test for exactly that — the post's title changes and the<b>node stays the same object.One computed, and what it buys
The computed returns the winning case, and
swap_swaps content when that changes. The case tuple is built once, so its identity is the memo key: while the same case keeps winning, a change to its value updates the branch in place and never rebuilds it. That gate —oldValue !== (value = compute())— is what a computed has and an effect does not, which is why the walk cannot simply live inside the swapper.The walk stops at the case that holds, so the block reads the values above the winner and no further. A case below the one that won is never asked, and never wakes the block when it changes — laziness that falls out of the early exit rather than being arranged.
Measured
The shape was reviewed against the alternatives — an index instead of the tuple (+11 B, same mechanics), no computed at all (breaks the in-place update), nested
if_(N computeds and N swap blocks),selector(a derivative of one source, and there are N here). All heavier; the current form stands.findover a hand-written loop costs a call per case — 5 ns per walk across 2, 4 and 8 cases — and saves 21 B gzip. The walk runs when a value changes, so the bytes win by the house rule; the trade-off is written down at the call site in case a profile ever says otherwise.Cost: +79 B gzip (7581 → 7660), one pin moves,
All publics (Gzip)7.6 → 7.7 kB.Tests
Four stories under
Logic/match_and eight tests written through them, the wayif_andswitch_are: the cascade with and without a default, the branch keeping its node while the value changes, a case below the winner staying unread, and the pair that documentsbatch— the cases moving together walk once, the same cases moving one after another walk twice and show the frame in between.Lint,
tsc --noEmitand 139 tests are green.