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