How about something like this:
function showtypetree(T, level=0)
println("\t" ^ level, T)
for t in subtypes(T)
(t != Any) && showtypetree(t, level+1)
end
end
This is still not type stable, since *_subtype *seems to use untyped sets:
https://github.com/JuliaLang/julia/blob/master/base/reflection.jl#L283
Not sure if this is an oversight, or if there are actually corner cases
making it impossible to type as Set{DataType}().
Fact is, with that change subtype is 10x faster and doesn't return
Vector{Any} anymore.
I opened a PR:
https://github.com/JuliaLang/julia/pull/18663
Best,
Simon
Am Sonntag, 25. September 2016 00:12:16 UTC+2 schrieb Brian Rogoff:
>
> ... of @code_warntype output.
>
> I was reading
> https://en.wikibooks.org/wiki/Introducing_Julia/Types#Investigating_types
> and I came across the following code, described as "not very elegant":
>
> level = 0
> function showtypetree(subtype)
> global level
> subtypelist = filter(asubtype -> asubtype != Any, subtypes(subtype))
> if length(subtypelist) > 0
> println("\t" ^ level, subtype)
> level += 1
> map(showtypetree, subtypelist)
> level -= 1
> else
> println("\t" ^ level, subtype)
> end
> end
>
> showtypetree(Number)
>
>
> Being unable to leave well enough alone, I decided to try to make it more
> elegant. After replacing the inelegant global variable with a nested
> function, I first noticed that the function returns '0', which is ugly. So,
> the increment operators return a value, which is unfortunate (any reason
> there's no increment with doesn't do that?) and the two branches of the if
> return different types. A special 'ignore' function patches that. map also
> builds and returns a value that's discarded. In OCaml we'd use an 'iter'
> instead of 'map', but Julia's 'for' can be a one-liner too. I left the
> print alone even though there's no need to repeatedly build those strings
> (print_nchars_before is easy) .In the end I got here
>
> ignore{T<:Any}(value::T)::Void = return
>
> function showtypetree(subtype::DataType)::Void
> level::Int64 = 0
> function nested(st::DataType)::Void
> subtypelist = filter(asubtype -> asubtype != Any, subtypes(st))
> if length(subtypelist) > 0
> println("\t" ^ level, st)
> level += 1
> for s in subtypelist nested(s) end
> ignore(level -= 1)
> else
> println("\t" ^ level, st)
> end
> end
> nested(subtype)
> end
>
>
> I still notice that when I do @code_warntype showtypetree(Number), I get
> some 'red', notably, level is shown as Core.Box, even though I explicitly
> type it. Is there some way to reduce the red in the @code_warntype for this
> function? Here's what I get in 0.6.0-dev.749
>
> julia> @code_warntype showtypetree(Number)
> Variables:
> #self#::#showtypetree
> subtype::Type{Number}
> level::Core.Box
> nested::Core.Box
>
> Body:
> begin
> level::Core.Box = $(Expr(:new, :(Core.Box)))
> nested::Core.Box = $(Expr(:new, :(Core.Box)))
> SSAValue(0) = Main.Void
> (Core.setfield!)(level::Core.Box,:contents,0)::Int64 # line 3:
> SSAValue(1) = $(Expr(:new, :(Main.#nested#2), :(level), :(nested)))
> (Core.setfield!)(nested::Core.Box,:contents,SSAValue(1))::#nested#2
> # line 16:
> return
> (Base.convert)(SSAValue(0),((Core.getfield)(nested::Core.Box,:contents)::Any)(subtype::Type{Number})::Any)::Void
> end::Void
>
>
> and I'm not sure how to remove the red and make the code more elegant.
> Ideas?
>
>