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. 
> >> 
> >> 
>

Reply via email to