diff --git a/README.md b/README.md index 2188e620..4a532289 100644 --- a/README.md +++ b/README.md @@ -106,7 +106,3 @@ end You can do this to your own functions in your own packages, to add `NamedDimsArray` support. If you implement it for any functions in a standard library, a PR would be very appreciated. - -### Caveats - -If multiple dimensions have the same names, indexing by name is considered undefined behaviour and should not be relied upon. diff --git a/src/name_core.jl b/src/name_core.jl index 52c35ba7..8f6a4ba4 100644 --- a/src/name_core.jl +++ b/src/name_core.jl @@ -180,8 +180,11 @@ order_named_inds(val::Val{L}; kw...) where {L} = order_named_inds(val, kw.data) @generated function order_named_inds(val::Val{L}, ni::NamedTuple{K}) where {L,K} tuple_issubset(K, L) || throw(DimensionMismatch("Expected subset of $L, got $K")) + seen = [] exs = map(L) do n if Base.sym_in(n, K) + n in seen && throw(ArgumentError("Can't index with :$n as this is repeated in $L")) + push!(seen, n) qn = QuoteNode(n) :(getfield(ni, $qn)) else diff --git a/test/functions.jl b/test/functions.jl index 62c59b72..3a20719b 100644 --- a/test/functions.jl +++ b/test/functions.jl @@ -28,6 +28,13 @@ using Statistics end end + @testset "repeated names" begin + ndt = NamedDimsArray(reshape(1:12, 2,3,2), (:x, :y, :x)) + @test sum(ndt, dims=:y) == sum(ndt, dims=2) + @test sum(ndt, dims=:x) == sum(ndt, dims=1) # chooses the first + @test dropdims(sum(ndt, dims=:x), dims=:x) == dropdims(sum(ndt, dims=1), dims=:x) + end + @testset "sort!" begin a = [1 9; 7 3] nda = NamedDimsArray(a, (:x, :y)) diff --git a/test/wrapper_array.jl b/test/wrapper_array.jl index 41ce815a..c934f7ea 100644 --- a/test/wrapper_array.jl +++ b/test/wrapper_array.jl @@ -137,6 +137,12 @@ end @test nda[findall(iseven, nda)] isa Vector @test dimnames(ndv[findall(iseven, ndv)]) == (:x,) end + + @testset "repeated names" begin + ndt = NamedDimsArray(rand(2,3,2), (:x, :y, :x)) + @test ndt[y=1] == ndt[:, 1, :] + @test_throws ArgumentError ndt[x=1] + end end