When creating a parameter type, there are no "default values",

I really want to do the following:

typealias CVODE_BDF CVODE_BDF{:Newton,:Dense} 

that is, allow the user to go to my CVODE_BDF function and, if they did not specify any of the type parameters, interpret it as CVODE_BDF{:Newton,:Dense} . I know that typealias doesn't actually work, but is there a way to mimic this? As in a function, read T.parameters[1] and somehow see that it is empty?

+8
types julia-lang
source share
4 answers

You can do this if the function accepts objects of this type, and not the type itself. For example.

 type MyObject{T} end const DefaultMyObject = MyObject{Int64}() f{T}(x::MyObject{T}=DefaultMyObject) = T f(), f(MyObj{Float64}()) 

gives

 (Int64,Float64) 
+4
source share

One possibility is to set type parameters ( {:Newton,:Dense} ) using Constructors .

Here is an example of the type of rational number defined in Julia (rational.jl):

 immutable Rational{T<:Integer} <: Real num::T den::T function Rational(num::T, den::T) if num == 0 && den == 0 error("invalid rational: 0//0") end g = gcd(den, num) num = div(num, g) den = div(den, g) new(num, den) end end 

In your example, you can define the constructor function in the type definition of CVODE_BDF and check the types and return to {:Newton,:Dense} CVODE_BDF {:Newton,:Dense} if they are not set.

+4
source share

Something like this work for you?

 type A{T, S} end 

Function Execution:

 f{T, S}(::Type{A{T,S}}) = T, S 

Default wrappers:

 f(::Type{A}) = f(A{1, 1}) f{T}(::Type{A{T}}) = f(A{T, 1}) f{S}(::Type{A{:default, S}}) = f(A{1, S}) 

Result:

 f(A) # (1,1) f(A{3,4}) # (3,4) f(A{0}) # (0,1) f(A{:default, 2}) # (1,2) 

Since the last call is a little ugly, objects are probably the best choice if maximum flexibility is needed. In addition, designers can set restrictions on parameters, so they do not need to check the function.

Edit:

If your function has more than one argument, adding too many methods for each combination of parameters. Instead, you can define a default method for each type (only one parameter for brevity):

 type A{T} end type B{T} end default{T}(::Type{A{T}}) = A{T} default(::Type{A}) = A{1} default{T}(::Type{B{T}}) = B{T} default(::Type{B}) = B{1} f{T,S}(::Type{A{T}}, ::Type{B{S}}) = T*S f{T<:A, S<:B}(a::Type{T}, b::Type{S}) = f(default(a), default(b)) 

At night, this has no overhead at runtime:

 julia> @code_llvm f(A,B) define i64 @julia_f_62099(%jl_value_t*, %jl_value_t*) #0 { top: ret i64 1 } 
+3
source share

Yes there is. If you execute Type{CVODE_BDF} , you can check the resulting parameters of the object. If CVODE_BDF was "empty", this will return the type CVODE_BDF with general parameters, otherwise they will be used by concrete ones.

Example (using Array , since I don't have CVODE_BDF ):

 julia> Type{Array}.parameters svec(Array{T,N}) julia> Type{Array{Float64, Int64}}.parameters svec(Array{Float64,Int64}) 

Function example:

 function f{T}(t::T) if Type(t).parameters == Type(Array).parameters t = Array{Int64, 1}; end return t; end 

 julia> f(Array{Int64, 1}) Array{Int64,1} julia> f(Array{Float64, 1}) Array{Float64,1} julia> f(Array) Array{Int64,1} 
+1
source share

All Articles