Get the red out!

classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

Get the red out!

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?

Reply | Threaded
Open this post in threaded view
|

Re: Get the red out!

Simon Danisch
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 <a href="https://en.wikibooks.org/wiki/Introducing_Julia/Types#Investigating_types" target="_blank" rel="nofollow" onmousedown="this.href=&#39;https://www.google.com/url?q\x3dhttps%3A%2F%2Fen.wikibooks.org%2Fwiki%2FIntroducing_Julia%2FTypes%23Investigating_types\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNGRQlmDeIjfLTenGWpQcFklFJlqHA&#39;;return true;" onclick="this.href=&#39;https://www.google.com/url?q\x3dhttps%3A%2F%2Fen.wikibooks.org%2Fwiki%2FIntroducing_Julia%2FTypes%23Investigating_types\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNGRQlmDeIjfLTenGWpQcFklFJlqHA&#39;;return true;">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?

Reply | Threaded
Open this post in threaded view
|

Re: Get the red out!

Brian Rogoff
Thanks Simon, way better, way more Julian. 

-- Brian

On Saturday, September 24, 2016 at 5:12:52 PM UTC-7, Simon Danisch wrote:
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:
<a href="https://github.com/JuliaLang/julia/blob/master/base/reflection.jl#L283" target="_blank" rel="nofollow" onmousedown="this.href=&#39;https://www.google.com/url?q\x3dhttps%3A%2F%2Fgithub.com%2FJuliaLang%2Fjulia%2Fblob%2Fmaster%2Fbase%2Freflection.jl%23L283\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNFUqZ87zkHVNt6Po_hkQa5Gsstj9Q&#39;;return true;" onclick="this.href=&#39;https://www.google.com/url?q\x3dhttps%3A%2F%2Fgithub.com%2FJuliaLang%2Fjulia%2Fblob%2Fmaster%2Fbase%2Freflection.jl%23L283\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNFUqZ87zkHVNt6Po_hkQa5Gsstj9Q&#39;;return true;">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:
<a href="https://github.com/JuliaLang/julia/pull/18663" target="_blank" rel="nofollow" onmousedown="this.href=&#39;https://www.google.com/url?q\x3dhttps%3A%2F%2Fgithub.com%2FJuliaLang%2Fjulia%2Fpull%2F18663\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNF0_qZhmEemBjubI6DtoJ8LGl3KVg&#39;;return true;" onclick="this.href=&#39;https://www.google.com/url?q\x3dhttps%3A%2F%2Fgithub.com%2FJuliaLang%2Fjulia%2Fpull%2F18663\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNF0_qZhmEemBjubI6DtoJ8LGl3KVg&#39;;return true;">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 <a href="https://en.wikibooks.org/wiki/Introducing_Julia/Types#Investigating_types" rel="nofollow" target="_blank" onmousedown="this.href=&#39;https://www.google.com/url?q\x3dhttps%3A%2F%2Fen.wikibooks.org%2Fwiki%2FIntroducing_Julia%2FTypes%23Investigating_types\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNGRQlmDeIjfLTenGWpQcFklFJlqHA&#39;;return true;" onclick="this.href=&#39;https://www.google.com/url?q\x3dhttps%3A%2F%2Fen.wikibooks.org%2Fwiki%2FIntroducing_Julia%2FTypes%23Investigating_types\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNGRQlmDeIjfLTenGWpQcFklFJlqHA&#39;;return true;">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?