Thanks for answering. Sorry I deleted my question after finding what I
wanted. If some people are interested, I like the two solutions below:
for t in (Vector, Matrix)
@eval begin
function f2(x::$t)
println("I'm an array")
$(t == Vector ? :(println("I'm a vector")) : :(println("I'm a
matrix")))
end
end
end
or even
@generated function f{T, N}(x::Array{T, N})
quote
println("I'm an array")
$(N == 1 ? :(println("I'm a vector")) : :(println("I'm a matrix")))
end
end
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?
>>
>