Skip to content

feat(match): match any AbstractVector via Indexable[...] and abstract-array heads - #89

Merged
Roger-luo merged 1 commit into
mainfrom
feat/indexable-abstractvector-match
Jul 16, 2026
Merged

Roger-luo merged 1 commit into
mainfrom
feat/indexable-abstractvector-match

Conversation

@Roger-luo

Copy link
Copy Markdown
Owner

Closes #36.

Motivation

@match view([1, 2, 3], :) begin
    [1, x, 3] => x
    _ => nothing
end

returned nothing because [1, x, 3] checks isa Vector, but view(...) produces a SubArray. As discussed in #36, bare [...] should stay Vector-only (an array literal builds a Vector, so the pattern deconstructs a Vector). This PR adds explicit syntax for matching any AbstractVector instead of widening [...].

What's new

Pattern Matches
[1, x, 3] Vector only (unchanged)
Int[1, x, 3] Vector{Int} — concrete head still means element type (unchanged)
Indexable[1, x, 3] any AbstractVector (reserved keyword)
AbstractVector[1, x, 3] / any abstract-array head isa that type
@match view([1, 2, 3], :) begin
    Indexable[1, x, 3] => x   # ⇒ 2   (also: AbstractVector[1, x, 3])
    _ => nothing
end

Design notes

  • Indexable is a scanner-level reserved keyword → Pattern.Indexable, matching AbstractVector. No import needed, can't be shadowed — that's its value over spelling out AbstractVector.
  • A Ref head T[...] is a container constraint only when T is an abstract array type (T <: AbstractArray && isabstracttype(unwrap_unionall(T))). Concrete heads (Int, Any, Union{...}, Vector, SubArray, ...) keep their existing element-type meaning, so nothing existing breaks.
  • Zero runtime cost. is_container_head is Base.@assume_effects :foldable; the is_container_head(T) ? T : Vector{T} branch const-folds away (verified via @code_typed).
  • firstindex-relative indexing. The shared collection-deconstruction machinery now indexes off firstindex/lastindex instead of a hard-coded 1, so non-1-based vectors (e.g. OffsetArray) deconstruct correctly. For Vector/Tuple, firstindex is 1 and folds away — no perf regression (perf-regression testset still passes).

Tests

  • Scanner: Indexable[...] → Pattern.Indexable, plus show round-trip.
  • Behavioral (test/match/examples/basic.jl): the exact should vector pattern match any AbstractVector? #36 case, Indexable/AbstractVector on views/ranges/plain vectors, bare [...] still rejecting a SubArray, typed splats under an abstract container head, and a minimal non-1-based OffsetVec <: AbstractVector across leading/trailing/interior splat shapes.

Full suite passes (data 325, match 140, derive 30, perf 5). Files are blue-formatted. Project.toml/CHANGELOG.md left untouched per release-please conventions.

🤖 Generated with Claude Code

…-array heads

Closes #36.

`[1, x, 3]` still matches only a concrete `Vector`, preserving the
constructor-inverse philosophy (an array literal builds a `Vector`, so it
deconstructs a `Vector`). Two new spellings opt into matching any
`AbstractVector` (a `view`/`SubArray`, range, ...):

- `Indexable[...]` — a reserved keyword recognised by the scanner.
- `AbstractVector[...]` / any abstract-array head — matched via `isa`.

A `Ref` head `T[...]` is now read as a *container* constraint when `T` is an
abstract array type; concrete heads (`Int`, `Vector`, ...) keep the
element-type reading (`Vector{T}`), so existing patterns are unchanged. The
container/element branch is chosen by `is_container_head`, which is
`@assume_effects :foldable` and folds out at compile time (no runtime cost).

The shared collection-deconstruction machinery now indexes relative to
`firstindex`/`lastindex` instead of a hard-coded `1`, so non-1-based vectors
(e.g. `OffsetArray`) deconstruct correctly. For `Vector`/`Tuple`, `firstindex`
is `1` and folds away, so there is no perf regression.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@vercel

vercel Bot commented Jul 14, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
moshi-jl Ignored Ignored Jul 14, 2026 2:03am

@codecov

codecov Bot commented Jul 14, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 92.85714% with 2 lines in your changes missing coverage. Please review.
✅ Project coverage is 91.91%. Comparing base (901dcbc) to head (f9c0cc1).

Files with missing lines Patch % Lines
src/match/emit/collection/vect.jl 83.33% 2 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main      #89      +/-   ##
==========================================
+ Coverage   91.86%   91.91%   +0.05%     
==========================================
  Files          43       43              
  Lines        1708     1732      +24     
==========================================
+ Hits         1569     1592      +23     
- Misses        139      140       +1     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@github-actions

Copy link
Copy Markdown
Contributor

Benchmark Results (Julia v1)

Time benchmarks
main f9c0cc1... main / f9c0cc1...
adt_transform/transform n=100 6.27 ± 0.23 μs 6.2 ± 0.24 μs 1.01 ± 0.054
adt_transform/transform n=1000 0.0589 ± 0.00098 ms 0.0584 ± 0.001 ms 1.01 ± 0.024
linked_list/sum n=100 0.511 ± 0.001 μs 0.511 ± 0.001 μs 1 ± 0.0028
linked_list/sum n=1000 5.6 ± 0.039 μs 5.58 ± 0.04 μs 1 ± 0.01
time_to_load 0.0816 ± 0.00064 s 0.081 ± 0.00012 s 1.01 ± 0.0081
Memory benchmarks
main f9c0cc1... main / f9c0cc1...
adt_transform/transform n=100 0.204 k allocs: 6.34 kB 0.204 k allocs: 6.34 kB 1
adt_transform/transform n=1000 2.02 k allocs: 0.0619 MB 2.02 k allocs: 0.0619 MB 1
linked_list/sum n=100 0 allocs: 0 B 0 allocs: 0 B
linked_list/sum n=1000 0 allocs: 0 B 0 allocs: 0 B
time_to_load 0.145 k allocs: 11 kB 0.145 k allocs: 11 kB 1

@Roger-luo
Roger-luo merged commit 9cab453 into main Jul 16, 2026
8 checks passed
@Roger-luo
Roger-luo deleted the feat/indexable-abstractvector-match branch July 16, 2026 00:45
github-actions Bot referenced this pull request Jul 16, 2026
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

should vector pattern match any AbstractVector?

1 participant