Skip to content

Commit 5044ef9

Browse files
authored
Subtype AbstractNamedUnitRange to AbstractNamedArray, not AbstractUnitRange (#170)
## Summary `AbstractNamedUnitRange` now subtypes `AbstractNamedArray` rather than `AbstractUnitRange`. A named unit range genuinely is an array (it has a size and cartesian indexing), but it is not a unit range: its elements are `NamedInteger`s, not plain stepped integers, so it never honored the `AbstractUnitRange` contract. Reparenting it under `AbstractNamedArray` (which stays `<: AbstractArray`) keeps the array behavior while letting it inherit the shared named-array interface instead of duplicating it. The range-specific behavior stays: the range `iterate`, `first`/`last`/`step`, `conj`, and a `setname` that rebuilds through `named` so the result stays a named unit range.
1 parent 818616e commit 5044ef9

1 file changed

Lines changed: 17 additions & 32 deletions

File tree

src/abstractnamedunitrange.jl

Lines changed: 17 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
1-
using TypeParameterAccessors: unspecify_type_parameters
2-
31
abstract type AbstractNamedUnitRange{T, Value <: AbstractUnitRange, Name} <:
4-
AbstractUnitRange{T} end
2+
AbstractNamedArray{T, 1, Value, Name} end
53

64
# Minimal interface.
75
denamed(r::AbstractNamedUnitRange) = throw(MethodError(denamed, Tuple{typeof(r)}))
@@ -14,28 +12,13 @@ namedunitrange(r::AbstractUnitRange, name) = NamedUnitRange(r, name)
1412
# Shorthand.
1513
named(r::AbstractUnitRange, name) = namedunitrange(r, name)
1614

17-
# Derived interface.
15+
# Derived interface. `setname` differs from the `AbstractNamedArray` method: it
16+
# rebuilds through `named` so the result stays a named unit range, not a named
17+
# array. The rest of the named interface (`==`, `hash`, `isnamed`, `denamedtype`,
18+
# `nametype`, `randname`, `show`, `isempty`) is inherited from `AbstractNamedArray`.
1819
# TODO: Use `Accessors.@set`?
1920
setname(r::AbstractNamedUnitRange, name) = named(denamed(r), name)
2021

21-
# TODO: Use `TypeParameterAccessors`.
22-
denamedtype(::Type{<:AbstractNamedUnitRange{<:Any, Value}}) where {Value} = Value
23-
nametype(::Type{<:AbstractNamedUnitRange{<:Any, <:Any, Name}}) where {Name} = Name
24-
25-
# Traits.
26-
isnamed(::Type{<:AbstractNamedUnitRange}) = true
27-
28-
# TODO: Should they also have the same base type?
29-
function Base.:(==)(r1::AbstractNamedUnitRange, r2::AbstractNamedUnitRange)
30-
return name(r1) == name(r2) && denamed(r1) == denamed(r2)
31-
end
32-
function Base.hash(r::AbstractNamedUnitRange, h::UInt)
33-
h = hash(Symbol(unspecify_type_parameters(typeof(r))), h)
34-
# TODO: Double check how this is handling blocking/sector information.
35-
h = hash(denamed(r), h)
36-
return hash(name(r), h)
37-
end
38-
3922
# Forward `conj` to the underlying range so graded axes flip their sector
4023
# arrows. The `Base.conj(::AbstractArray{<:Real}) = x` fallback would
4124
# otherwise short-circuit before the inner range is touched.
@@ -66,7 +49,18 @@ function Base.getindex(r::AbstractNamedUnitRange, I::AbstractNamedInteger)
6649
@assert name(r) == name(I)
6750
return getindex_named(r, denamed(I))
6851
end
69-
Base.isempty(r::AbstractNamedUnitRange) = isempty(denamed(r))
52+
53+
# Named ranges are not `AbstractUnitRange`s, so `CartesianIndices` over a tuple of
54+
# them has no Base method; dename to the parent ranges so `CartesianIndices` of a
55+
# named tensor matches the parent's.
56+
function Base.CartesianIndices(
57+
rs::Tuple{AbstractNamedUnitRange, Vararg{AbstractNamedUnitRange}}
58+
)
59+
return CartesianIndices(denamed.(rs))
60+
end
61+
62+
# Show compactly; the inherited `AbstractNamedArray` text/plain show is multiline.
63+
Base.show(io::IO, ::MIME"text/plain", r::AbstractNamedUnitRange) = show(io, r)
7064

7165
function Base.AbstractUnitRange{Int}(r::AbstractNamedUnitRange)
7266
return AbstractUnitRange{Int}(denamed(r))
@@ -81,15 +75,6 @@ function Base.iterate(r::AbstractNamedUnitRange, i)
8175
return (next, next)
8276
end
8377

84-
function randname(rng::AbstractRNG, r::AbstractNamedUnitRange)
85-
return named(denamed(r), randname(rng, name(r)))
86-
end
87-
88-
function Base.show(io::IO, r::AbstractNamedUnitRange)
89-
print(io, "named(", denamed(r), ", ", repr(name(r)), ")")
90-
return nothing
91-
end
92-
9378
struct NamedColon{Name} <: Function
9479
name::Name
9580
end

0 commit comments

Comments
 (0)