I need the fields color and year to be Int and ASCIIString, respectively,
and I can't just make the types Color and Year type aliases of Int and
ASCIIString, since I need these abstract types to distinguish different
types of Car for the purposes of multiple dispatch.
Basically let's say I have 6 possible features and I want to include
features 3, 5 and 6. And let's say those features are ASCIIString, Int and
Int, respectively, then I want to be able to write:
Car{Feature3, Feature5, Feature6}(a, b, c)
where a is a string, and b and c are both integers, and then I want the
constructor to return:
Car{Void, Void, Feature3, Void, Feature5, Feature6}(nothing, nothing, a,
nothing, b, c)
On Friday, April 15, 2016 at 12:18:56 AM UTC-7, Mauro wrote:
>
>
> On Fri, 2016-04-15 at 07:28, Anonymous <[email protected] <javascript:>>
> wrote:
> > OP here,
> >
> > So it looks like the consensus is to use a single type with un-used
> > features set to nothing. I've actually been playing around with this
> > approach since I posted this question. Here's what I've got:
> >
> > abstract AbstractCar
> >
> > abstract Color
> > abstract Year
> >
> > typealias ColorOrVoid Union{Color, Void}
> > typealias YearOrVoid Union{Year, Void}
> >
> > type Car{C<:ColorOrVoid, Y<:YearOrVoid} <: AbstractCar
> > color::typeMap(C)
> > year::typeMap(Y)
> > end
>
> This should work:
>
> type Car{C<:ColorOrVoid, Y<:YearOrVoid} <: AbstractCar
> color::C
> year::Y
> end
>
> (Aside:
> I think using a function inside the type definition is only possible if
> it can be evaluated at compile time (I might be wrong though). Consider
> this example:
>
> julia> g(T) = Vector{T}
> g (generic function with 1 method)
>
> julia> type B{T}
> b::g(T)
> end
>
> julia> B([1,2])
> B{Int64}([1,2])
>
> julia> h(T) = string(Int.name.name)[1]=="I" ? Int : Float64
> h (generic function with 1 method)
>
> julia> h(AbstractString)
> Float64
>
> julia> type C{T}
> c::h(T)
> end
> WARNING: static parameter T does not occur in signature for call at
> none:2.
> The method will not be callable.
>
> end-aside)
>
> > where the function typeMap will send Void to itself, Color to
> ASCIIString
> > and Year to Int. However I tried doing this and I got an error, I
> probably
> > the way to do this is with meta-programming and macros, but I'm not sure
> > how since I'm a complete novice at meta-programming.
> >
> > I would also like to have outer constructors which allow me to avoid
> having
> > to enter Void for all the un-used features, so if I'm only interested in
> > Year, I would have an outer constructor of the form:
> >
> > Car{Year}(y::Int) = Car{Void, Year}(nothing, y)
> >
> > However this gives me an error saying that *static parameter Year does
> not
> > occur in signature for call at none*.
>
> Outer constructors are a bit hard to grok because type parameter feature
> twice, in the same location, but have a completely different
> meaning:
>
> Car{Year}(y::Int) = Car{Void, Year}(nothing, y)
> ^^^^ ^^^^^^^^^^
> function parameter type parameters
>
> Function parameters need to be inferred from the arguments, whereas type
> parameters are part of the type. (this might get cleared up in the future)
>
> Consider that for just an ordinary function, you cannot do this:
>
> f{T<:Int}(i::I) = 5
> # now call it like so
> f{Int}(4) # error
>
> Anyway, the solution is just (assuming Color and Year can be
> distinguished by type):
>
> Car(y::Year) = Car{Void, Year}(nothing, y)
> Car(c::Color) = Car{Color,Void}(c, nothing)
> Car(c::Color, y::Year) = Car{Color,Year}(c, y)
>
> If you want to explicate specify the type then (like is used in
> Julia-Base for e.g. array constructors):
>
> Car(T::Type{Year}, y) = Car{Void, Year}(nothing, y)
> ...
>
>
> > On Thursday, April 14, 2016 at 10:08:53 PM UTC-7, Toivo Henningsson
> wrote:
> >>
> >> As you say, it's a lot of types. If you would really need to
> instantiate
> >> an exponential number of types then maybe you should reconsider,
> because
> >> the jit compiler has to do quite a lot of work for each type that is
> used.
> >>
> >> But if you're not actually going to instantiate such a humongous number
> of
> >> them, or if you really want to be able to use specialization and
> dispatch
> >> in this way: How about a middle road where you use a parametric type
> and
> >> set the types of all unused fields to Void (the type of nothing)? That
> >> should be able to support the cases that you mentioned.
> >>
> >> Also, in many cases, storage for a value worth known type of eg Void is
> >> free, since it is known that there is only one instance. The exception
> is
> >> if the value could be uninitialized as well.
> >>
> >>
>