Get the red out!

178 views
Skip to first unread message

Brian Rogoff

unread,
Sep 24, 2016, 6:12:16 PM9/24/16
to julia-users
... 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?

Simon Danisch

unread,
Sep 24, 2016, 8:12:52 PM9/24/16
to julia-users
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:

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:

Best,
Simon

Brian Rogoff

unread,
Sep 27, 2016, 5:19:52 PM9/27/16
to julia-users
Thanks Simon, way better, way more Julian. 

-- Brian
Reply all
Reply to author
Forward
0 new messages