If you look at @code_native you'll see that the branch which still exists in code_warntype is eliminated.
On Wed, 2015-09-30 at 14:06, Matt <[email protected]> wrote: > Also, both Stefan and you mention that the branching is eliminated in the > first method. But if if I use on the first version > > @code_warntype f(rand(10, 10)) > > Body: > > begin # none, line 2: > > (Base.println)(Base.STDOUT,"I'm an array")::Any # line 3: > > unless 2 === 1::Bool goto 0 # line 4: > > return (Base.println)(Base.STDOUT,"I'm a vector")::Any > > goto 2 > > 0: # line 5: > > unless 2 === 2::Bool goto 1 # line 6: > > return (Base.println)(Base.STDOUT,"I'm a matrix")::Any > > goto 2 > > 1: > > return > > 2: > > end::Any > > > > while all other methods do eliminate branching: > > > Body: > > begin # none, line 2: > > (Base.println)(Base.STDOUT,"I'm an array")::Any # line 3: > > return (Base.println)(Base.STDOUT,"I'm a matrix")::Any > > end::Any > > > > On Tuesday, September 29, 2015 at 8:57:10 PM UTC-4, Stefan Karpinski wrote: >> >> The branch on the first version will be eliminated. The second version is >> far more idiomatic, however. Consider that the second version is trivially >> extensible to more types while the first version cannot be extended at all. >> >> On Tuesday, September 29, 2015, Matt <[email protected] <javascript:>> >> wrote: >> >>> I want to write a method that is very similar between two types, with >>> slight divergences. I'd like to write it avoiding code duplication. >>> >>> To take a simple example, let's say that the two types are Vector and >>> Matrix. The method must print "I'm an array" for the two types, and then >>> prints "I'm a vector" if the object is a vector, "I'm a matrix" if the >>> object is a matrix. >>> >>> One way write this method is to use a "run time" dispatch >>> >>> function f{T, N}(x::Array{T, N}) >>> println("I'm an array") >>> if N == 1 >>> println("I'm a vector") >>> elseif N == 2 >>> println("I'm a matrix") >>> end >>> end >>> f2(rand(10, 10)) >>> @code_warntype f2(rand(10, 10)) >>> >>> A way to dispatch at compile time is to define as many auxiliary function >>> as there are differing lines >>> >>> function _ansfunction(x::Vector) >>> println("I'm a vector") >>> end >>> function _ansfunction(x::Matrix) >>> println("I'm a matrix") >>> end >>> function f1(x) >>> println("I'm an array") >>> _ansfunction(x) >>> end >>> f1(rand(10, 10)) >>> @code_warntype f1(rand(10, 10)) >>> >>> Another solution would be to iterate through two NTuples, where N is the >>> number of differing lines >>> >>> for (t, x) in ((:Vector, :(println("I'm a vector"))), >>> (:Matrix, :(println("I'm a Matrix")))) >>> @eval begin >>> function f2(x::$t) >>> println("I'm an array") >>> $x >>> end >>> end >>> end >>> f2(rand(10, 10)) >>> @code_warntype f2(rand(10, 10)) >>> >>> >>> These two last solutions work, but I really prefer the syntax of first >>> solution : it allows to write the differing lines exactly at the place >>> they're needed, when they're needed. It really starts to mattes when there >>> are a few differing lines. Is there a syntax as clear as the first >>> solution, but that "branch" at compile time? >>> >>
