Skip to content

Commit 41f6257

Browse files
committed
Change functions user needs to define
1 parent f38db8e commit 41f6257

File tree

3 files changed

+32
-37
lines changed

3 files changed

+32
-37
lines changed

Project.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ version = "0.4.0"
55

66
[deps]
77
Requires = "ae029012-a4dd-5104-9daa-d747884805df"
8+
Tricks = "410a4b4d-49e4-4fbc-ab6d-cb71b17b3775"
89

910
[weakdeps]
1011
Unitful = "1986cc42-f94f-5a68-af5c-568840ba703d"
@@ -19,8 +20,8 @@ julia = "1.6"
1920

2021
[extras]
2122
Ratios = "c84ed2f1-dad5-54f0-aa8e-dbefe2724439"
22-
SaferIntegers = "88634af6-177f-5301-88b8-7819386cfa38"
2323
SafeTestsets = "1bc83da4-3b8d-516f-aca4-4fe02f6d838f"
24+
SaferIntegers = "88634af6-177f-5301-88b8-7819386cfa38"
2425
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
2526
Unitful = "1986cc42-f94f-5a68-af5c-568840ba703d"
2627

src/types.jl

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,11 @@
1+
import Tricks: static_fieldnames
2+
13
const DEFAULT_DIM_TYPE = FixedRational{Int32, 2^4 * 3^2 * 5^2 * 7}
24
const DEFAULT_VALUE_TYPE = Float64
35

46
abstract type AbstractQuantity{T,R} end
57
abstract type AbstractDimensions{R} end
68

7-
constructor_of(::Type{D}) where {D<:AbstractDimensions} = D
8-
constructor_of(::Type{D}) where {R,D<:AbstractDimensions{R}} = D.name.wrapper
9-
constructor_of(::Type{Q}) where {Q<:AbstractQuantity} = Q
10-
constructor_of(::Type{Q}) where {T,Q<:AbstractQuantity{T}} = Q.body.name.wrapper
11-
constructor_of(::Type{Q}) where {T,R,Q<:AbstractQuantity{T,R}} = Q.name.wrapper
12-
139
"""
1410
Dimensions{R}
1511
@@ -36,7 +32,6 @@ which is by default a rational number.
3632
- `Dimensions(::Type{R}; kws...)` or `Dimensions{R}(; kws...)`: Pass a subset of dimensions as keyword arguments, with the output type set to `Dimensions{R}`.
3733
- `Dimensions{R}(args...)`: Pass all the dimensions as arguments, with the output type set to `Dimensions{R}`.
3834
- `Dimensions{R}(d::Dimensions)`: Copy the dimensions from another `Dimensions` object, with the output type set to `Dimensions{R}`.
39-
4035
"""
4136
struct Dimensions{R<:Real} <: AbstractDimensions{R}
4237
length::R
@@ -48,12 +43,14 @@ struct Dimensions{R<:Real} <: AbstractDimensions{R}
4843
amount::R
4944
end
5045

51-
(::Type{D})(::Type{R}; kws...) where {R,D<:AbstractDimensions} = D{R}((tryrationalize(R, get(kws, k, zero(R))) for k in fieldnames(D))...)
46+
(::Type{D})(::Type{R}; kws...) where {R,D<:AbstractDimensions} = D{R}((tryrationalize(R, get(kws, k, zero(R))) for k in static_fieldnames(D))...)
5247
(::Type{D})(; kws...) where {D<:AbstractDimensions} = D(DEFAULT_DIM_TYPE; kws...)
5348

54-
(::Type{D})(args...) where {R,D<:AbstractDimensions{R}} = constructor_of(D)(Base.Fix1(convert, R).(args)...)
55-
(::Type{D})(; kws...) where {R,D<:AbstractDimensions{R}} = constructor_of(D)(R; kws...)
56-
(::Type{D})(d::AbstractDimensions) where {R,D<:AbstractDimensions{R}} = D((getfield(d, k) for k in fieldnames(D))...)
49+
(::Type{D})(args...) where {R,D<:AbstractDimensions{R}} = dimension_constructor(D)(Base.Fix1(convert, R).(args)...)
50+
(::Type{D})(; kws...) where {R,D<:AbstractDimensions{R}} = dimension_constructor(D)(R; kws...)
51+
(::Type{D})(d::AbstractDimensions) where {R,D<:AbstractDimensions{R}} = D((getfield(d, k) for k in static_fieldnames(D))...)
52+
53+
new_dimensions(::Type{D}, dims...) where {D<:AbstractDimensions} = dimension_constructor(D)(dims...)
5754

5855

5956
"""
@@ -94,10 +91,12 @@ struct Quantity{T,R} <: AbstractQuantity{T,R}
9491
Quantity{T,R}(q::Quantity) where {T,R} = Quantity(convert(T, q.value), Dimensions{R}(dimension(q)))
9592
end
9693

94+
new_quantity(::Type{QD}, l, r) where {QD<:Union{AbstractQuantity,AbstractDimensions}} = quantity_constructor(QD)(l, r)
95+
9796
# All that is needed to make an `AbstractQuantity` work:
9897
dimension_name(::Dimensions, k::Symbol) = (length="m", mass="kg", time="s", current="A", temperature="K", luminosity="cd", amount="mol")[k]
99-
new_dimensions(::Type{<:Dimensions}, dims...) = Dimensions(dims...)
100-
new_quantity(::Type{<:Union{<:Quantity,<:Dimensions}}, l, r) = Quantity(l, r)
98+
quantity_constructor(::Type{<:Union{Quantity,Dimensions}}) = Quantity
99+
dimension_constructor(::Type{<:Union{Quantity,Dimensions}}) = Dimensions
101100

102101
struct DimensionError{Q1,Q2} <: Exception
103102
q1::Q1

src/utils.jl

Lines changed: 18 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,23 @@
1-
@generated function map_dimensions(f::F, args::AbstractDimensions...) where {F<:Function}
2-
dimension_type = first(args)
3-
dimension_names = Base.fieldnames(dimension_type)
4-
output = :(new_dimensions($dimension_type))
5-
for dim in dimension_names
6-
f_expr = :(f())
7-
for i=1:length(args)
8-
push!(f_expr.args, :(args[$i].$dim))
9-
end
10-
push!(output.args, f_expr)
11-
end
12-
return output
1+
import Tricks: static_fieldnames
2+
3+
function map_dimensions(f::F, args::AbstractDimensions...) where {F<:Function}
4+
dimension_type = promote_type(typeof(args).parameters...)
5+
dimension_names = static_fieldnames(dimension_type)
6+
return new_dimensions(
7+
dimension_type,
8+
(
9+
f((getfield(arg, dim) for arg in args)...)
10+
for dim in dimension_names
11+
)...
12+
)
1313
end
14-
@generated function all_dimensions(f::F, args::AbstractDimensions...) where {F<:Function}
15-
dimension_type = first(args)
16-
dimension_names = Base.fieldnames(dimension_type)
17-
output = Expr(:&&)
14+
function all_dimensions(f::F, args::AbstractDimensions...) where {F<:Function}
15+
dimension_type = promote_type(typeof(args).parameters...)
16+
dimension_names = static_fieldnames(dimension_type)
1817
for dim in dimension_names
19-
f_expr = :(f())
20-
for i=1:length(args)
21-
push!(f_expr.args, :(args[$i].$dim))
22-
end
23-
push!(output.args, f_expr)
18+
f((getfield(arg, dim) for arg in args)...) || return false
2419
end
25-
return output
20+
return true
2621
end
2722

2823
Base.float(q::AbstractQuantity{T}) where {T<:AbstractFloat} = convert(T, q)
@@ -33,7 +28,7 @@ Base.convert(::Type{T}, q::AbstractQuantity) where {T<:Real} =
3328
end
3429

3530
Base.isfinite(q::AbstractQuantity) = isfinite(ustrip(q))
36-
Base.keys(d::AbstractDimensions) = Base.fieldnames(typeof(d))
31+
Base.keys(d::AbstractDimensions) = static_fieldnames(typeof(d))
3732
# TODO: Make this more generic.
3833
Base.iszero(d::AbstractDimensions) = all_dimensions(iszero, d)
3934
Base.iszero(q::AbstractQuantity) = iszero(ustrip(q))

0 commit comments

Comments
 (0)