Hey,

Sorry I'm not sure what you're referring too.

Just to clarify. I have written 3 functions in the first subject. The first 
function uses run time dispatch,  the second use sub-auxiliary functions at 
every differing line, the third uses the @eval style. I like the syntax of 
the first function, but I want the performance of the second or third 
function (ie compile time dispatch)
In my second message, have posted a 4th and 5th way, with a syntax close to 
the first function (that I like), but with compile-time dispatch. The 4th 
method is just another way to write the 3rd method. The 5th method uses 
@generated, and I understand it may be overkill (at least for the simple 
example!).

I'm not sure which one you are advising me to use. I think you're referring 
to the second one, right? But I really dont like the idea of defining new 
functions for every differing line between the two methods  (including 
finding meaningful new function names). Another issue is that, if a 
diverging line involves a lot of local variables, all of them must be 
passed to the function (including typically a loop counter), which makes 
the whole thing unreadable. Thanks for the explanation of the @eval use in 
Base, I did not realize this.


On Tuesday, September 29, 2015 at 10:33:07 PM UTC-4, Jameson wrote:
>
> 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 <[email protected] <javascript:>> 
> 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 <[email protected]> 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