Skip to content
This repository was archived by the owner on Mar 11, 2022. It is now read-only.

Commit b67a83a

Browse files
committed
Improve custom pretty-printing
1 parent 4e08601 commit b67a83a

File tree

13 files changed

+330
-261
lines changed

13 files changed

+330
-261
lines changed

src/DiffinDiffsBase.jl

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ export @fieldequal,
2626
@unpack,
2727
,
2828
exampledata,
29-
sprintcompact,
3029

3130
EleOrVec,
3231
TreatmentSharpness,
@@ -57,15 +56,13 @@ export @fieldequal,
5756
parse_treat,
5857

5958
StatsStep,
60-
@show_StatsStep,
6159
AbstractStatsProcedure,
6260
SharedStatsStep,
6361
PooledStatsProcedure,
6462
pool,
6563
StatsSpec,
6664
@specset,
6765

68-
check_data,
6966
CheckData,
7067

7168
DiffinDiffsEstimator,

src/StatsProcedures.jl

Lines changed: 97 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,18 @@
11
"""
2-
StatsStep{F<:Function,SpecNames,TraceNames}
2+
StatsStep{Alias,F<:Function,SpecNames,TraceNames}
33
44
Specify the function and arguments for moving a step
55
in an [`AbstractStatsProcedure`](@ref).
66
An instance of `StatsStep` is callable.
77
88
# Parameters
9+
- `Alias::Symbol`: alias of the type for pretty-printing.
910
- `F<:Function`: type of the function to be called by `StatsStep`.
1011
- `SpecNames::NTuple{N,Symbol}`: keys for arguments from [`StatsSpec`](@ref).
1112
- `TraceNames::NTuple{N,Symbol}`: keys for arguments from objects returned by a previous `StatsStep`.
1213
1314
# Methods
14-
(step::StatsStep{F,S,T})(ntargs::NamedTuple; verbose::Bool=false) where {F,S,T}
15+
(step::StatsStep{A,F,S,T})(ntargs::NamedTuple; verbose::Bool=false) where {A,F,S,T}
1516
1617
Call an instance of function of type `F` with arguments from `ntargs`
1718
formed by accessing the keys in `S` and `T` sequentially.
@@ -23,13 +24,14 @@ a message with the name of the `StatsStep` is printed to `stdout`.
2324
## Returns
2425
- `NamedTuple`: named intermidiate results.
2526
"""
26-
struct StatsStep{F<:Function,SpecNames,TraceNames} end
27+
struct StatsStep{Alias,F<:Function,SpecNames,TraceNames} end
2728

28-
_f(step::StatsStep{F}) where {F} = F.instance
29-
_specnames(step::StatsStep{F,S}) where {F,S} = S
30-
_tracenames(step::StatsStep{F,S,T}) where {F,S,T} = T
29+
_alias(step::StatsStep{A}) where A = A
30+
_f(step::StatsStep{A,F}) where {A,F} = F.instance
31+
_specnames(step::StatsStep{A,F,S}) where {A,F,S} = S
32+
_tracenames(step::StatsStep{A,F,S,T}) where {A,F,S,T} = T
3133

32-
function (step::StatsStep{F,S,T})(ntargs::NamedTuple; verbose::Bool=false) where {F,S,T}
34+
function (step::StatsStep{A,F,S,T})(ntargs::NamedTuple; verbose::Bool=false) where {A,F,S,T}
3335
verbose || (haskey(ntargs, :verbose) && ntargs.verbose) &&
3436
println(" Running ", step)
3537
args = NamedTuple{(S...,T...)}(ntargs)
@@ -43,48 +45,63 @@ function (step::StatsStep{F,S,T})(ntargs::NamedTuple; verbose::Bool=false) where
4345
end
4446
end
4547

46-
macro show_StatsStep(step, name)
47-
return esc(quote
48-
function Base.show(io::IO, s::$step)
49-
if get(io, :compact, false)
50-
print(io, $name)
51-
else
52-
println(io, "StatsStep: ", $name)
53-
println(io, " arguments from StatsSpec: ", $step.parameters[2])
54-
print(io, " arguments from trace: ")
55-
$step.parameters[3] == () ? print(io, "()") : print(io, $step.parameters[3])
56-
end
57-
end
58-
end)
48+
show(io::IO, s::StatsStep{A}) where A = print(io, A)
49+
50+
function show(io::IO, ::MIME"text/plain", s::StatsStep{A,F,S,T}) where {A,F,S,T}
51+
print(io, A, " (", typeof(s).name, " that calls ")
52+
fmod = F.name.mt.module
53+
fmod == Main ? print(io, F.name.mt.name) : print(io, fmod, ".", F.name.mt.name)
54+
println(io, "):")
55+
println(io, " arguments from StatsSpec: ", S)
56+
print(io, " arguments from trace: ")
57+
T==() ? print(io, "()") : print(io, T)
5958
end
6059

6160
"""
62-
AbstractStatsProcedure{T<:NTuple{N,StatsStep} where N}
61+
AbstractStatsProcedure{Alias,T<:NTuple{N,StatsStep} where N}
6362
6463
Supertype for all types specifying the procedure for statistical estimation or inference.
6564
66-
The procedure is determined by the parameter `T`,
67-
which is a tuple of [`StatsStep`](@ref).
6865
Fallback methods for indexing and iteration are defined for
6966
all subtypes of `AbstractStatsProcedure`.
67+
68+
# Parameters
69+
- `Alias::Symbol`: alias of the type for pretty-printing.
70+
- `T<:NTuple{N,StatsStep}`: steps involved in the procedure.
7071
"""
71-
abstract type AbstractStatsProcedure{T<:NTuple{N,StatsStep} where N} end
72+
abstract type AbstractStatsProcedure{A,T<:NTuple{N,StatsStep} where N} end
7273

73-
length(p::AbstractStatsProcedure{T}) where T = length(T.parameters)
74+
length(p::AbstractStatsProcedure{A,T}) where {A,T} = length(T.parameters)
7475
eltype(::Type{<:AbstractStatsProcedure}) = StatsStep
75-
firstindex(p::AbstractStatsProcedure{T}) where T = firstindex(T.parameters)
76-
lastindex(p::AbstractStatsProcedure{T}) where T = lastindex(T.parameters)
76+
firstindex(p::AbstractStatsProcedure{A,T}) where {A,T} = firstindex(T.parameters)
77+
lastindex(p::AbstractStatsProcedure{A,T}) where {A,T} = lastindex(T.parameters)
7778

78-
function getindex(p::AbstractStatsProcedure{T}, i) where T
79+
function getindex(p::AbstractStatsProcedure{A,T}, i) where {A,T}
7980
fs = T.parameters[i]
8081
return fs isa Type && fs <: StatsStep ? fs.instance : [f.instance for f in fs]
8182
end
8283

83-
getindex(p::AbstractStatsProcedure{T}, i::Int) where T = T.parameters[i].instance
84+
getindex(p::AbstractStatsProcedure{A,T}, i::Int) where {A,T} = T.parameters[i].instance
8485

8586
iterate(p::AbstractStatsProcedure, state=1) =
8687
state > length(p) ? nothing : (p[state], state+1)
8788

89+
show(io::IO, p::AbstractStatsProcedure{A}) where A = print(io, A)
90+
91+
function show(io::IO, ::MIME"text/plain", p::AbstractStatsProcedure{A,T}) where {A,T}
92+
nstep = length(p)
93+
print(io, A, " (", typeof(p).name, " with ", nstep, " step")
94+
if nstep > 0
95+
nstep > 1 ? print(io, "s):\n ") : print(io, "):\n ")
96+
for (i, step) in enumerate(p)
97+
print(io, step)
98+
i < nstep && print(io, " |> ")
99+
end
100+
else
101+
print(io, ")")
102+
end
103+
end
104+
88105
"""
89106
SharedStatsStep{T<:StatsStep,PID}
90107
@@ -100,18 +117,6 @@ struct SharedStatsStep{T<:StatsStep,PID}
100117
step::T
101118
end
102119

103-
#show(io::IO, step::SharedStatsStep) = show(io, step.step)
104-
105-
function show(io::IO, step::SharedStatsStep{T,PID}) where {T,PID}
106-
if get(io, :compact, false)
107-
show(io, step.step)
108-
else
109-
print(io, "Shared")
110-
show(io, step.step)
111-
print(io, "\n shared by ", length(PID), " procedures")
112-
end
113-
end
114-
115120
==(x::SharedStatsStep{T,PID1}, y::SharedStatsStep{T,PID2}) where {T,PID1,PID2} =
116121
x.step == y.step && Set(PID1) == Set(PID2)
117122

@@ -121,6 +126,14 @@ _f(s::SharedStatsStep) = _f(s.step)
121126
_specnames(s::SharedStatsStep) = _specnames(s.step)
122127
_tracenames(s::SharedStatsStep) = _tracenames(s.step)
123128

129+
show(io::IO, s::SharedStatsStep) = print(io, s.step)
130+
131+
function show(io::IO, ::MIME"text/plain", s::SharedStatsStep{T,PID}) where {T,PID}
132+
nps = length(PID)
133+
print(io, s.step, " (StatsStep shared by ", nps, " procedure")
134+
nps > 1 ? print(io, "s)") : print(io, ")")
135+
end
136+
124137
const SharedStatsSteps = NTuple{N, Vector{SharedStatsStep}} where N
125138
const StatsProcedures = NTuple{N, AbstractStatsProcedure} where N
126139

@@ -211,15 +224,15 @@ function iterate(ps::PooledStatsProcedure, state=deepcopy(ps.steps))
211224
state = state[BitArray(length.(state).>0)]
212225
length(state) > 0 || return nothing
213226
firsts = first.(state)
214-
for i in length(firsts)
227+
for i in 1:length(firsts)
215228
nshared = length(_sharedby(firsts[i]))
216229
if nshared == 1
217230
deleteat!(state[i],1)
218231
return (firsts[i], state)
219232
else
220-
shared = firsts.==firsts[i]
233+
shared = BitArray(s==firsts[i] for s in firsts)
221234
if sum(shared) == nshared
222-
for p in state[BitArray(shared)]
235+
for p in state[shared]
223236
deleteat!(p, 1)
224237
end
225238
return (firsts[i], state)
@@ -229,19 +242,33 @@ function iterate(ps::PooledStatsProcedure, state=deepcopy(ps.steps))
229242
error("bad construction of $(typeof(ps))")
230243
end
231244

245+
show(io::IO, ps::PooledStatsProcedure) = print(io, typeof(ps).name)
246+
247+
function show(io::IO, ::MIME"text/plain", ps::PooledStatsProcedure{P,S,N}) where {P,S,N}
248+
print(io, typeof(ps).name, " with ", N, " step")
249+
N > 1 ? print(io, "s ") : print(io, " ")
250+
nps = length(P.parameters)
251+
print(io, "from ", nps, " procedure")
252+
nps > 1 ? print(io, "s:") : print(io, ":")
253+
for p in P.parameters
254+
print(io, "\n ", p.parameters[1])
255+
end
256+
end
257+
232258
"""
233-
StatsSpec{T<:AbstractStatsProcedure}
259+
StatsSpec{Alias,T<:AbstractStatsProcedure}
234260
235261
Record the specification for a statistical procedure of type `T`.
262+
236263
An instance of `StatsSpec` is callable and
237264
its fields provide all information necessary for conducting the procedure.
265+
An optional name for the specification can be attached as parameter `Alias`.
238266
239267
# Fields
240-
- `name::String`: an optional name for the specification.
241-
- `args::NamedTuple`: arguments for the [`StatsStep`](@ref) in `T`.
268+
- `args::NamedTuple`: arguments for the [`StatsStep`](@ref)s in `T`.
242269
243270
# Methods
244-
(sp::StatsSpec{T})(; verbose::Bool=false, keep=nothing, keepall::Bool=false)
271+
(sp::StatsSpec{A,T})(; verbose::Bool=false, keep=nothing, keepall::Bool=false)
245272
246273
Execute the procedure of type `T` with the arguments specified in `args`.
247274
By default, only an object with a key `result` assigned by a [`StatsStep`](@ref)
@@ -252,40 +279,39 @@ or the last value returned by the last [`StatsStep`](@ref) is returned.
252279
- `keep=nothing`: names (of type `Symbol`) of additional objects to be returned.
253280
- `keepall::Bool=false`: return all objects returned by each step.
254281
"""
255-
struct StatsSpec{T<:AbstractStatsProcedure}
256-
name::String
282+
struct StatsSpec{Alias,T<:AbstractStatsProcedure}
257283
args::NamedTuple
284+
StatsSpec(name::Union{Symbol,String},
285+
T::Type{<:AbstractStatsProcedure}, args::NamedTuple) =
286+
new{Symbol(name),T}(args)
258287
end
259288

260-
StatsSpec(T::Type{<:AbstractStatsProcedure}, name::String, args::NamedTuple) =
261-
StatsSpec{T}(name, args)
262-
263289
"""
264-
==(x::StatsSpec{T}, y::StatsSpec{T})
290+
==(x::StatsSpec{A1,T}, y::StatsSpec{A2,T})
265291
266292
Test whether two instances of [`StatsSpec`](@ref)
267293
with the same parameter `T` also have the same field `args`.
268294
269295
See also [`≊`](@ref).
270296
"""
271-
==(x::StatsSpec{T}, y::StatsSpec{T}) where T =
297+
==(x::StatsSpec{A1,T}, y::StatsSpec{A2,T}) where {A1,A2,T} =
272298
x.args == y.args
273299

274300
"""
275-
≊(x::StatsSpec{T}, y::StatsSpec{T})
301+
≊(x::StatsSpec{A1,T}, y::StatsSpec{A2,T})
276302
277303
Test whether two instances of [`StatsSpec`](@ref)
278304
with the same parameter `T` also have the field `args`
279305
containing the same sets of key-value pairs
280306
while ignoring the orders.
281307
"""
282-
(x::StatsSpec{T}, y::StatsSpec{T}) where T =
308+
(x::StatsSpec{A1,T}, y::StatsSpec{A2,T}) where {A1,A2,T} =
283309
x.args y.args
284310

285-
_isnamed(sp::StatsSpec) = sp.name != ""
286-
_procedure(sp::StatsSpec{T}) where T = T
311+
_procedure(sp::StatsSpec{A,T}) where {A,T} = T
287312

288-
function (sp::StatsSpec{T})(; verbose::Bool=false, keep=nothing, keepall::Bool=false) where T
313+
function (sp::StatsSpec{A,T})(;
314+
verbose::Bool=false, keep=nothing, keepall::Bool=false) where {A,T}
289315
args = verbose ? merge(sp.args, (verbose=true,)) : sp.args
290316
ntall = foldl(|>, T(), init=sp.args)
291317
if keepall
@@ -307,6 +333,16 @@ function (sp::StatsSpec{T})(; verbose::Bool=false, keep=nothing, keepall::Bool=f
307333
end
308334
end
309335

336+
show(io::IO, sp::StatsSpec{A,T}) where {A,T} = print(io, A==Symbol("") ? "unnamed" : A)
337+
338+
_show_args(io::IO, sp::StatsSpec) = nothing
339+
340+
function show(io::IO, ::MIME"text/plain", sp::StatsSpec{A,T}) where {A,T}
341+
print(io, A==Symbol("") ? "unnamed" : A, " (", typeof(sp).name,
342+
" for ", T.parameters[1], ")")
343+
_show_args(io, sp)
344+
end
345+
310346
function run_specset(sps::AbstractVector{<:StatsSpec};
311347
verbose::Bool=false, keep=nothing, keepall::Bool=false)
312348
traces = Vector{NamedTuple}(undef, length(sps))
@@ -356,7 +392,7 @@ function parse_specset_options(args)
356392
end
357393

358394
function spec_walker(x, parsers, formatters)
359-
@capture(x, StatsSpec(formatter_(parser_(rawargs__))))(;o__) || return x
395+
@capture(x, StatsSpec(formatter_(parser_(rawargs__)))(;o__)) || return x
360396
push!(parsers, parser)
361397
push!(formatters, formatter)
362398
length(o) > 0 &&

src/did.jl

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,16 @@
11
"""
2-
DiffinDiffsEstimator{T} <: AbstractStatsProcedure{T}
2+
DiffinDiffsEstimator{A,T} <: AbstractStatsProcedure{A,T}
33
44
Specify the estimation procedure for difference-in-differences.
55
"""
6-
struct DiffinDiffsEstimator{T} <: AbstractStatsProcedure{T} end
6+
struct DiffinDiffsEstimator{A,T} <: AbstractStatsProcedure{A,T} end
77

88
"""
99
DefaultDID <: DiffinDiffsEstimator
1010
1111
Default difference-in-differences estimator selected based on the context.
1212
"""
13-
const DefaultDID = DiffinDiffsEstimator{Tuple{}}
14-
15-
show(io::IO, d::Type{DefaultDID}) = print(io, "DefaultDID")
13+
const DefaultDID = DiffinDiffsEstimator{:DefaultDID, Tuple{}}
1614

1715
_argpair(arg::Type{<:DiffinDiffsEstimator}) = :d => arg
1816
_argpair(arg::AbstractString) = :name => String(arg)
@@ -100,16 +98,12 @@ macro didspec(exprs...)
10098
return esc(:(didspec($(args...); $(kwargs...))))
10199
end
102100

103-
function show(io::IO, sp::StatsSpec{T}) where {T<:DiffinDiffsEstimator}
104-
print(io, "StatsSpec{", sprintcompact(T), "}")
105-
_isnamed(sp) && print(io, ": ", sp.name)
106-
if get(io, :compact, false) || !haskey(sp.args, :tr) && !haskey(sp.args, :pr)
107-
return
108-
elseif !_isnamed(sp)
109-
print(io, ":")
101+
function _show_args(io::IO, sp::StatsSpec{A,<:DiffinDiffsEstimator}) where A
102+
if haskey(sp.args, :tr) || haskey(sp.args, :pr)
103+
print(io, ":")
104+
haskey(sp.args, :tr) && print(io, "\n ", sp.args[:tr])
105+
haskey(sp.args, :pr) && print(io, "\n ", sp.args[:pr])
110106
end
111-
haskey(sp.args, :tr) && print(io, "\n ", sprintcompact(sp.args[:tr]))
112-
haskey(sp.args, :pr) && print(io, "\n ", sprintcompact(sp.args[:pr]))
113107
end
114108

115109
function did(args...; verbose::Bool=false, keep=nothing, keepall::Bool=false, kwargs...)

0 commit comments

Comments
 (0)