Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,9 @@ jobs:
env:
JULIA_NUM_THREADS: 4
- uses: julia-actions/julia-processcoverage@v1
- uses: codecov/codecov-action@v3
- uses: codecov/codecov-action@v4
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
with:
file: lcov.info
test-nightly:
Expand Down
5 changes: 4 additions & 1 deletion Project.toml
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
name = "TupleTools"
uuid = "9d95972d-f1c8-5527-a6e0-b4b365fa01f6"
authors = ["Jutho Haegeman"]
version = "1.4.3"
version = "1.5.0"

[deps]

[compat]
julia = "1"
Aqua = "0.8"
Random = "1"
Test = "1"

[extras]
Aqua = "4c88cf16-eb10-579e-8560-4a9242c79595"
Expand Down
19 changes: 19 additions & 0 deletions src/TupleTools.jl
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,15 @@ end
_permute(t::NTuple{N,Any}, p::NTuple{N,Int}) where {N} = getindices(t, p)
_permute(t::NTuple{N,Any}, p) where {N} = ntuple(n -> t[p[n]], StaticLength(N))

"""
circshift(t::NTuple{N,Any}, i::Int) -> ::NTuple{N,Any}

Circularly shift the elements of tuple `t` by `i` positions.
"""
function circshift(t::NTuple{N,Any}, i::Int) where {N}
return ntuple(n -> t[mod1(n - i, N)], StaticLength(N))
end

"""
isperm(p) -> ::Bool

Expand Down Expand Up @@ -373,4 +382,14 @@ diff(v::Tuple{}) = () # similar to diff([])
diff(v::Tuple{Any}) = ()
diff(v::Tuple) = (v[2] - v[1], diff(Base.tail(v))...)

"""
indexin(a::Tuple, b::Tuple)

Return a tuple containing the first indices in `b` of the elements of `a`. If an element
of `a` is not in `b`, then the corresponding index will be `nothing`.
"""
function indexin(a::Tuple, b::Tuple)
return ntuple(i -> findfirst(==(a[i]), b), length(a))
end
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess this one is not type stable, because findfirst can return nothing?

One possibility would be to explicitly error when elements are missing, but then it differs from the Base method and we should maybe name it differently.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed, the Base method always returns a Vector{Union{Nothing,Int}}, and is therefore type stable. I checked the inferred type of this function, and it's still NTuple{N, Union{Nothing,Int}}, which might be fine as supposedly small type unions are ok.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure. I just hope it doesn't lead to type instabilities further down in methods that use this, but I guess not.


end # module
3 changes: 2 additions & 1 deletion test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -78,18 +78,19 @@ using Base: tail, front
@test @inferred(TupleTools.isperm(t)) == true
@test @inferred(TupleTools.isperm((1, 2, 1))) == false
@test @inferred(TupleTools.permute(t, t)) == (p[p]...,)
@test @inferred(TupleTools.circshift(t, 3)) == tuple(circshift(p, 3)...)

@test @inferred(TupleTools.vcat()) == ()
@test @inferred(TupleTools.diff(())) == ()
@test @inferred(TupleTools.diff((1,))) == ()
@test @inferred(TupleTools.diff((1, 2, 3))) == (1, 1)

@test TupleTools.sort((2, 1, 3.0)) === (1, 2, 3.0)
@test TupleTools.indexin(TupleTools.getindices(t, (1, 2, 3)), t) == (1, 2, 3)
end

@testset "TupleTools quality assurance with Aqua" begin
using Aqua
Aqua.test_all(TupleTools;
project_toml_formatting=(VERSION >= v"1.9"),
unbound_args=false)
end