edit of previous post: 

I have color and year reversed, color should be ASCIIString and year should 
be Int, same thing with Color and Year.

On Friday, April 15, 2016 at 12:56:16 AM UTC-7, Anonymous wrote:
>
> 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]> 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