As Stefan mentioned, the `@generated` function below is equivalent to the
first function you posted, except that it is worse style since it is not
extensible, will generally require more memory, it is less readable (and it
seems to be giving the wrong answer for N > 2 and N == 0?)

The Julia-style is to use the second function that you posted, since it is
extensible and provides an appropriate separation (abstraction) between
behavior and implementation details.

The `@eval`-style function is used heavily in Base to generate a variety of
ccall's that can be heavily templated. It doesn't make sense to use the
usual Julia-style for these functions since the c-functions themselves are
not extensible. So this style code is most appropriate when your code is
providing language interoperability with a static language. It isn't
particularly well suited for writing code within Julia since it is rather
verbose, the compile-time and runtime constructs get mixed rather awkwardly
in the same code, and some essential parts of the code (in this case `t`),
get separated pretty far from their use sites


On Tue, Sep 29, 2015 at 9:17 PM Matt <matthewn...@gmail.com> wrote:

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