On Fri, 2016-04-15 at 09:56, Anonymous <[email protected]> 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.
Maybe you need to introduce your Color and Year types. However if they
alias to different types then your good.
typealias MyYear Int
typealias MyColor ASCIIString
Car(y::MyYear) = Car{Void, Year}(nothing, y)
Car(c::MyColor) = Car{Color,Void}(c, nothing)
Car(c::MyColor, y::MyYear) = Car{Color,Year}(c, y)
(Note though that this will construct types which have abstract
field-types. Those are bad for performance (but only worry about this
in critical code), have a look at the performance section of the docs)
> 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)
Well, outer constructors cannot work like this.
> 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.
>> >>
>> >>
>>