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

Reply via email to