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 <matth...@gmail.com <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? >> >