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?
>>
>

Reply via email to