Skip to content

Commit

Permalink
Merge 6cc32fd into 13f15ed
Browse files Browse the repository at this point in the history
  • Loading branch information
goretkin committed Feb 10, 2021
2 parents 13f15ed + 6cc32fd commit f2107e2
Show file tree
Hide file tree
Showing 5 changed files with 77 additions and 21 deletions.
56 changes: 56 additions & 0 deletions .github/workflows/ci.yml
@@ -0,0 +1,56 @@
name: CI
on:
- push
- pull_request
jobs:
test:
name: Julia ${{ matrix.version }} - ${{ matrix.os }} - ${{ matrix.arch }} - ${{ github.event_name }}
runs-on: ${{ matrix.os }}
strategy:
matrix:
version:
- '1.2' # minimum Julia version that the package supports.
- '1' # Leave this line unchanged. '1' will automatically expand to the latest stable 1.x release of Julia.
- 'nightly'
os:
- ubuntu-latest
arch:
- x64
steps:
- uses: actions/checkout@v2
- uses: julia-actions/setup-julia@v1
with:
version: ${{ matrix.version }}
arch: ${{ matrix.arch }}
- uses: actions/cache@v1
env:
cache-name: cache-artifacts
with:
path: ~/.julia/artifacts
key: ${{ runner.os }}-test-${{ env.cache-name }}-${{ hashFiles('**/Project.toml') }}
restore-keys: |
${{ runner.os }}-test-${{ env.cache-name }}-
${{ runner.os }}-test-
${{ runner.os }}-
- uses: julia-actions/julia-buildpkg@latest
- uses: julia-actions/julia-runtest@latest
- uses: julia-actions/julia-processcoverage@v1
- uses: julia-actions/julia-uploadcodecov@latest
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
docs:
name: Documentation
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: julia-actions/setup-julia@v1
with:
version: '1.5' # 1.6 will break doctests due to type aliases, until the tests are updated
- run: |
julia --project=docs -e '
using Pkg
Pkg.develop(PackageSpec(path=pwd()))
Pkg.instantiate()'
- run: julia --project=docs docs/make.jl
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
3 changes: 3 additions & 0 deletions Project.toml
Expand Up @@ -2,6 +2,9 @@ name = "FrankenTuples"
uuid = "7e584817-dab4-53a9-9a51-4037a36b0ad0"
version = "0.0.1"

[compat]
julia = "1.2"

[extras]
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"

Expand Down
2 changes: 1 addition & 1 deletion docs/src/index.md
Expand Up @@ -39,14 +39,14 @@ Base.first
Base.tail
Base.empty
Base.eltype
Base.map
```

## Additional Methods

These are some additional ways to use `FrankenTuple`s.
The most interesting of these is perhaps `hasmethod`, which permits looking for methods
that have particular keyword arguments.
This is not currently possible with the generic method in Base.

```@docs
Base.hasmethod
Expand Down
31 changes: 11 additions & 20 deletions src/FrankenTuples.jl
Expand Up @@ -300,7 +300,7 @@ julia> f(x::Int; y=3, z=4) = x + y + z;
julia> hasmethod(f, FrankenTuple{Tuple{Int},(:y,)})
true
julia> hasmethod(f, FrankenTuple{Tuple{Int},(:a,)) # no keyword `a`
julia> hasmethod(f, FrankenTuple{Tuple{Int},(:a,)}) # no keyword `a`
false
julia> g(; a, b, kwargs...) = +(a, b, kwargs...);
Expand All @@ -312,30 +312,14 @@ true
function Base.hasmethod(f::Function,
::Type{FrankenTuple{T,names,NT}};
world=typemax(UInt)) where {T<:Tuple,names,NT<:Tuple}
hasmethod(f, T) || return false
m = which(f, T)
Base.max_world(m) <= world || return false
kws = Base.kwarg_decl(m, Core.kwftype(typeof(f)))
isempty(kws) === isempty(names) || return false
for (i, k) in enumerate(kws)
if endswith(String(k), "...")
deleteat!(kws, i)
return issubset(kws, names)
end
end
issubset(names, kws)
hasmethod(f, T, names; world=world)
end
function Base.hasmethod(f::Function,
::Type{FrankenTuple{T,names}};
world=typemax(UInt)) where {T<:Tuple,names}
NT = Tuple{Iterators.repeated(Any, length(names))...}
hasmethod(f, FrankenTuple{T,names,NT}; world=world)
end
function Base.hasmethod(f::Function,
::Type{FrankenTuple{T,(),Tuple{}}};
world=typemax(UInt)) where {T<:Tuple}
hasmethod(f, T; world=world)
end

"""
ftuple(args...; kwargs...)
Expand Down Expand Up @@ -418,7 +402,14 @@ julia> ftcall(mapreduce, ftuple(abs2, -, 1:4; init=0))
-30
```
"""
ftcall(f::Function, ft::FrankenTuple) = f(Tuple(ft)...; NamedTuple(ft)...)
ftcall(f::Function, ft::FrankenTuple{Tuple{},(),Tuple{}}) = f()
ftcall(f, ft::FrankenTuple) = f(Tuple(ft)...; NamedTuple(ft)...)
ftcall(f, ft::FrankenTuple{Tuple{},(),Tuple{}}) = f()

# NOTE: this method signature makes sure we don't define map(f)
function Base.map(f, ft::FrankenTuple, fts::FrankenTuple...)
t = map(f, Tuple(ft), map(Tuple, fts)...)
nt = map(f, NamedTuple(ft), map(NamedTuple, fts)...)
FrankenTuple(t, nt)
end

end # module
6 changes: 6 additions & 0 deletions test/runtests.jl
Expand Up @@ -100,3 +100,9 @@ h(x::String; a, kwargs...) = x * a

@test !hasmethod(f, FrankenTuple{Tuple{Int},(:y,)}, world=typemin(UInt))
end

@testset "map" begin
@test FrankenTuple((11,22), (x=33,y=44)) == map(+, FrankenTuple((1,2), (x=3,y=4)), FrankenTuple((10, 20), (x=30,y=40)))
@test_throws Exception map(+, FrankenTuple((1,2), (x=3,y=4)), FrankenTuple((10, 20), (x=30,)))
@test_throws Exception map(+, FrankenTuple((1,2), (x=3,y=4)), FrankenTuple((10,), (x=30,y=40)))
end

0 comments on commit f2107e2

Please sign in to comment.