Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Parametric Type Creation

Tags:

julia

I'm struggling to understand parametric type creation in julia. I know that I can create a type with the following:

type EconData
    values
    dates::Array{Date}
    colnames::Array{ASCIIString}

    function EconData(values, dates, colnames)
    if size(values, 1) != size(dates, 1)
        error("Date/data dimension mismatch.")
    end
    if size(values, 2) != size(colnames, 2)
        error("Name/data dimension mismatch.")
    end
    new(values, dates, colnames)
    end
end

ed1 = EconData([1;2;3], [Date(2014,1), Date(2014,2), Date(2014,3)], ["series"])

However, I can't figure out how to specify how values will be typed. It seems reasonable to me to do something like

type EconData{T}
   values::Array{T}
   ...
   function EconData(values::Array{T}, dates, colnames)
   ...

However, this (and similar attempts) simply produce and error:

ERROR: `EconData{T}` has no method matching EconData{T}(::Array{Int64,1}, ::Array{Date,1}, ::Array{ASCIIString,2})

How can I specify the type of values?

like image 386
David Kelley Avatar asked May 28 '15 23:05

David Kelley


1 Answers

The answer is that things get funky with parametric types and inner constructors - in fact, I think its probably the most confusing thing in Julia. The immediate solution is to provide a suitable outer constructor:

using Dates

type EconData{T}
    values::Vector{T}
    dates::Array{Date}
    colnames::Array{ASCIIString}
    function EconData(values, dates, colnames)
        if size(values, 1) != size(dates, 1)
            error("Date/data dimension mismatch.")
        end
        if size(values, 2) != size(colnames, 2)
            error("Name/data dimension mismatch.")
        end
        new(values, dates, colnames)
    end
end
EconData{T}(v::Vector{T},d,n) = EconData{T}(v,d,n)

ed1 = EconData([1,2,3], [Date(2014,1), Date(2014,2), Date(2014,3)], ["series"])

What also would have worked is to have done

ed1 = EconData{Int}([1,2,3], [Date(2014,1), Date(2014,2), Date(2014,3)], ["series"])

My explanation might be wrong, but I think the probably is that there is no parametric type constructor method made by default, so you have to call the constructor for a specific instantiation of the type (my second version) or add the outer constructor yourself (first version).

Some other comments: you should be explicit about dimensions. i.e. if all your fields are vectors (1D), use Vector{T} or Array{T,1}, and if their are matrices (2D) use Matrix{T} or Array{T,2}. Make it parametric on the dimension if you need to. If you don't, slow code could be generated because functions using this type aren't really sure about the actual data structure until runtime, so will have lots of checks.

like image 98
IainDunning Avatar answered Nov 09 '22 10:11

IainDunning