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