Re: [julia-users] Metaprogramming and Dispatch

2015-09-29 Thread Stefan Karpinski
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  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?
>


Re: [julia-users] Metaprogramming and Dispatch

2015-09-29 Thread Jameson Nash
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  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  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?
>>>
>>


Re: [julia-users] Metaprogramming and Dispatch

2015-09-29 Thread Matt
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  
> 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  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"
   

Re: [julia-users] Metaprogramming and Dispatch

2015-09-29 Thread Matt
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  
> 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?
>>
>