Skip to content

Commit

Permalink
Merge pull request #7 from putianyi889/version-0.1.6
Browse files Browse the repository at this point in the history
Version 0.2.0
  • Loading branch information
putianyi889 authored Dec 6, 2023
2 parents f34f48b + 4e277a1 commit f466460
Show file tree
Hide file tree
Showing 7 changed files with 123 additions and 26 deletions.
26 changes: 26 additions & 0 deletions .github/workflows/Documentation.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
name: Documentation

on:
push:
branches:
- master # update to match your development branch (master, main, dev, trunk, ...)
tags: '*'
pull_request:

jobs:
build:
permissions:
contents: write
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: julia-actions/setup-julia@v1
with:
version: '1.9'
- name: Install dependencies
run: julia --project=docs/ -e 'using Pkg; Pkg.add(url="https://github.com/putianyi889/PTYQoL.jl"); Pkg.develop(PackageSpec(path=pwd())); Pkg.instantiate()'
- name: Build and deploy
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # If authenticating with GitHub Actions token
DOCUMENTER_KEY: ${{ secrets.DOCUMENTER_KEY }} # If authenticating with SSH deploy key
run: julia --project=docs/ docs/make.jl
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "PTYQoL"
uuid = "551ad714-b11a-4605-8871-12721def4e72"
authors = ["Tianyi Pu <[email protected]> and contributors"]
version = "0.1.5"
version = "0.2.0"

[weakdeps]
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@

Want just an easy feature that Julia or some package doesn't have, while the PR gets rejected/takes forever to get merged? This is a personal collection of little things that makes coding easier while not breaking existing things.

Full of type piracies. Do file an issue if some feature becomes a part of Julia/some other package.
Full of type piracies. Do file an issue if this package does break other things or becomes a part of Julia/some other package.

Rule of new version: an external PR is merged, or the number of line changes reach 100.
Rule of new version: an external PR is merged, an issue is resolved, or the number of line changes reach 100.
7 changes: 4 additions & 3 deletions docs/make.jl
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,13 @@ using PTYQoL
makedocs(
sitename = "PTYQoL",
format = Documenter.HTML(),
doctest = false,
modules = [PTYQoL]
)

# Documenter can also automatically deploy documentation to gh-pages.
# See "Hosting Documentation" and deploydocs() in the Documenter manual
# for more information.
#=deploydocs(
repo = "<repository url>"
)=#
deploydocs(
repo = "github.com/putianyi889/PTYQoL.jl.git"
)
16 changes: 16 additions & 0 deletions src/PTYQoL.jl
Original file line number Diff line number Diff line change
Expand Up @@ -75,4 +75,20 @@ getindex(A::CartesianIndex, i) = CartesianIndex(Tuple(A)[i])
import Base: copy
copy(t::Tuple) = t

import Base: Fix1, Fix2, +, -, *, /, //, show, Splat
(t::NTuple{N, Function})(x...) where N = tuple((f(x...) for f in t)...)
for op in (:+, :*, :-, :/, ://)
@eval begin
$op() = nothing # ambiguity
$op(f::Function...) = (splat($op), f)
$op(f::Function, c::Number) = Fix2($op, c) f
$op(c::Number, f::Function) = Fix1($op, c) f
show(io::IO, f::ComposedFunction{<:Fix1{typeof($op)}}) = print(io, '(', f.outer.x, $op, f.inner, ')')
show(io::IO, f::ComposedFunction{<:Fix2{typeof($op)}}) = print(io, '(', f.inner, $op, f.outer.x, ')')
show(io::IO, f::ComposedFunction{Splat{typeof($op)}, <:Tuple{Function, Function}}) = print(io, '(', f.inner[1], $op, f.inner[2], ')')
end
end
show(io::IO, f::ComposedFunction{<:Fix1}) = print(io, f.outer.f, '(', f.outer.x, ',', f.inner, ')')
show(io::IO, f::ComposedFunction{<:Fix2}) = print(io, f.outer.f, '(', f.inner, ',', f.outer.x, ')')

end
91 changes: 71 additions & 20 deletions src/Utils.jl
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import Base: front
export seealso, fields, @struct_equal, @struct_copy, @struct_map
export seealso, fields, @struct_all, @struct_any, @struct_copy, @struct_map

docref(s) = "[`$(string(s))`](@ref)"

Expand All @@ -9,7 +9,7 @@ langenum(s, t...) = s * ", " *langenum(t...)
"""
seealso(s...)
Produce the "See also" parts of docstrings. $(seealso(docref, langenum))
Produce the "See also" parts of docstrings.
```jldoctest
julia> seealso(sin)
Expand All @@ -32,9 +32,10 @@ The same as `fieldnames`, but is `@generated` so is fast.
@generated fields(::Type{T}) where T = fieldnames(T)

"""
@struct_equal(TYP)
@struct_all(TYP, op)
@struct_all(TYP, ops...)
Generate `Base.==` for comparing structs of type `TYP`.
Define the operator of the type `TYP` by applying the operator to each field and return true only when all the results are true. $(seealso("@struct_any", "@struct_copy", "@struct_map"))
# Example
```jldoctest
Expand All @@ -49,33 +50,83 @@ Foo(1, 1)
julia> y = Foo(1.0,1.0)
Foo(1.0, 1.0)
julia> x==y
false
julia> x==y, isequal(x,y)
(false, false)
julia> @struct_equal Foo;
julia> isapprox(x,y)
ERROR: MethodError: no method matching isapprox(::Foo, ::Foo)
julia> x==y
true
julia> isfinite(x)
ERROR: MethodError: no method matching isfinite(::Foo)
julia> @struct_all Foo Base.:(==) Base.isequal Base.isapprox Base.isfinite
julia> x==y, isequal(x,y), isapprox(x,y), isfinite(x)
(true, true, true, true)
```
"""
macro struct_equal(TYP)
macro struct_all(TYP, op)
quote
function $(esc(op))(A::$(esc(TYP))...)
Base.all($(esc(op))(getfield.(A, p)...) for p in fields($(esc(TYP))))
end
end
end

macro struct_all(TYP, ops...)
esc(quote
import Base: ==
function ==(A::T1, B::T2) where {T1<:$TYP, T2<:$TYP}
for p in fields($TYP)
if getfield(A, p) != getfield(B, p)
return false
end
end
return true
@struct_all($TYP, $(Base.first(ops)))
@struct_all($TYP, $(Base.tail(ops)...))
end)
end

"""
@struct_any(TYP, op)
@struct_any(TYP, ops...)
Define the binary operator of the type `TYP` by applying the operator to each field and return true when any of the results is true. $(seealso("@struct_all", "@struct_copy", "@struct_map"))
# Example
```jldoctest
julia> struct Foo
a
b
end
julia> x = Foo(Inf, NaN)
Foo(Inf, NaN)
julia> isinf(x)
ERROR: MethodError: no method matching isinf(::Foo)
julia> isnan(x)
ERROR: MethodError: no method matching isnan(::Foo)
julia> @struct_any Foo Base.isinf Base.isnan
julia> isinf(x), isnan(x)
(true, true)
```
"""
macro struct_any(TYP, op)
quote
function $(esc(op))(A::$(esc(TYP))...)
Base.any($(esc(op))(getfield.(A, p)...) for p in fields($(esc(TYP))))
end
end
end

macro struct_any(TYP, ops...)
esc(quote
@struct_any($TYP, $(Base.first(ops)))
@struct_any($TYP, $(Base.tail(ops)...))
end)
end

"""
@struct_copy(TYP)
Generate `Base.copy` for copying structs of type `TYP`.
Generate `Base.copy` for copying structs of type `TYP`. $(seealso("@struct_all", "@struct_any", "@struct_map"))
# Example
```jldoctest
Expand Down Expand Up @@ -108,7 +159,7 @@ end
@struct_map(TYP, op)
@struct_map(TYP, ops...)
Define the function(s) of the type `TYP` by applying the function(s) to each field and generate a new `TYP` with the values. The generated function(s) are somehow faster than the naive implementation.
Define the function(s) of the type `TYP` by applying the function(s) to each field and generate a new `TYP` with the values. The generated function(s) are somehow faster than the naive implementation. $(seealso("@struct_all", "@struct_any", "@struct_copy"))
# Example
```jldoctest
Expand Down
3 changes: 3 additions & 0 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,9 @@ end
@test Fix2(+, 3) ^ 5 == Fix2(+, 15)
@test Fix2(*, 4) ^ 3 == Fix2(*, 64)
@test Fix2(^, 2) Fix2(^, 3) == Fix2(^, 6)

@test (sin+1)(1) 1+sin(1)
@test (2sin*cos)(1) sin(2)
end

@testset "Tuple copy" begin
Expand Down

0 comments on commit f466460

Please sign in to comment.