Skip to content

Commit

Permalink
Use markdown files as docstring
Browse files Browse the repository at this point in the history
  • Loading branch information
tkf committed Oct 2, 2019
1 parent ee593e5 commit d5bad22
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 66 deletions.
6 changes: 4 additions & 2 deletions docs/src/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
```@index
```

```@autodocs
Modules = [ConstructionBase]
```@docs
ConstructionBase
ConstructionBase.constructorof
ConstructionBase.setproperties
```
81 changes: 17 additions & 64 deletions src/ConstructionBase.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3,71 +3,24 @@ module ConstructionBase
export setproperties
export constructorof

# Use markdown files as docstring:
for (name, path) in [
:ConstructionBase => joinpath(dirname(@__DIR__), "README.md"),
:constructorof => joinpath(@__DIR__, "constructorof.md"),
]
# Don't fail when somehow importing docstrings doesn't work (we
# don't loose any functionalities for that). We use explicit
# `@docs` in `docs/src/index.md` to make sure importing docstrings
# succeeds in CI.
try
include_dependency(path)
str = read(path, String)
@eval @doc $str $name
catch err
@error "Failed to import docstring for $name" exception=(err, catch_backtrace())
end
end

"""
constructorof(T::Type)
Return an object `ctor` that can be used to construct objects of type `T`
from their field values. Typically `ctor` will be the type `T` with all parameters removed:
```jldoctest
julia> using ConstructionBase
julia> struct T{A,B}
a::A
b::B
end
julia> constructorof(T{Int,Int})
T
```
It is however not guaranteed, that `ctor` is a type at all:
```jldoctest; setup = :(using ConstructionBase)
julia> struct S
a
b
checksum
S(a,b) = new(a,b,a+b)
end
julia> ConstructionBase.constructorof(::Type{<:S}) =
(a, b, checksum=a+b) -> (@assert a+b == checksum; S(a,b))
julia> constructorof(S)(1,2)
S(1, 2, 3)
julia> constructorof(S)(1,2,4)
ERROR: AssertionError: a + b == checksum
```
Instead `ctor` can be any object that satisfies the following properties:
* It must be possible to reconstruct an object from its fields:
```julia
ctor = constructorof(typeof(obj))
@assert obj == ctor(fieldvalues(obj)...)
@assert typeof(obj) == typeof(ctor(fieldvalues(obj)...))
```
* The other direction should hold for as many values of `args` as possible:
```julia
ctor = constructorof(T)
fieldvalues(ctor(args...)) == args
```
For instance given a suitable parametric type it should be possible to change
the type of its fields:
```jldoctest; setup = :(using ConstructionBase)
julia> struct T{A,B}
a::A
b::B
end
julia> t = T(1,2)
T{Int64,Int64}(1, 2)
julia> constructorof(typeof(t))(1.0, 2)
T{Float64,Int64}(1.0, 2)
julia> constructorof(typeof(t))(10, 2)
T{Int64,Int64}(10, 2)
```
"""
@generated function constructorof(::Type{T}) where T
getfield(parentmodule(T), nameof(T))
end
Expand Down
62 changes: 62 additions & 0 deletions src/constructorof.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
constructorof(T::Type)

Return an object `ctor` that can be used to construct objects of type `T`
from their field values. Typically `ctor` will be the type `T` with all parameters removed:
```jldoctest
julia> using ConstructionBase
julia> struct T{A,B}
a::A
b::B
end
julia> constructorof(T{Int,Int})
T
```
It is however not guaranteed, that `ctor` is a type at all:
```jldoctest; setup = :(using ConstructionBase)
julia> struct S
a
b
checksum
S(a,b) = new(a,b,a+b)
end
julia> ConstructionBase.constructorof(::Type{<:S}) =
(a, b, checksum=a+b) -> (@assert a+b == checksum; S(a,b))
julia> constructorof(S)(1,2)
S(1, 2, 3)
julia> constructorof(S)(1,2,4)
ERROR: AssertionError: a + b == checksum
```
Instead `ctor` can be any object that satisfies the following properties:
* It must be possible to reconstruct an object from its fields:
```julia
ctor = constructorof(typeof(obj))
@assert obj == ctor(fieldvalues(obj)...)
@assert typeof(obj) == typeof(ctor(fieldvalues(obj)...))
```
* The other direction should hold for as many values of `args` as possible:
```julia
ctor = constructorof(T)
fieldvalues(ctor(args...)) == args
```
For instance given a suitable parametric type it should be possible to change
the type of its fields:
```jldoctest; setup = :(using ConstructionBase)
julia> struct T{A,B}
a::A
b::B
end
julia> t = T(1,2)
T{Int64,Int64}(1, 2)
julia> constructorof(typeof(t))(1.0, 2)
T{Float64,Int64}(1.0, 2)
julia> constructorof(typeof(t))(10, 2)
T{Int64,Int64}(10, 2)
```

0 comments on commit d5bad22

Please sign in to comment.