Tuples of Ints as type parameters v0.5/0.6


#1

Hi,

I have a situation where I want to have a few tuples as type parameters. In v0.5 I used to have

# works in v0.5
immutable foo{a, b, N, T}
    foo{N, T}(a_::NTuple{N, T}, b_::NTuple{N, T}) = new()
end
foo(a, b) = foo{a, b, length(a), eltype(a)}(a, b)
@show foo((1, 2), (3, 4))

where the inner constructor enforces the constraint that the lengths of the tuple must be the same.

I am converting my packages to v0.6 but I am not able to achieve the same result. The main difference is that now all type parameters need to be specified in the inner constructor. Here is an example of something that does not work

# does not work in v0.6
struct foo{a, b, N, T}
    (::foo){a, b, N, T}(a_::NTuple{N, T}, b_::NTuple{N, T}) = new{a, b, N, T}()
end
foo(a, b) = foo{a, b, length(a), eltype(a)}(a, b)
@show foo((1, 2), (3, 4))

as the parameters a, b do not appear in the function signature.

Thanks,

Davide


#2

This works both in 0.5 and 0.6:

julia> immutable foo{a, b, N, T}
           (::Type{foo{a,b,N,T}}){a,b,N,T}(::NTuple{N, T}, ::NTuple{N, T}) = new{a,b,N,T}()
       end

julia> foo(a, b) = foo{a, b, length(a), eltype(a)}(a, b)
foo{a,b,N,T}

julia> foo((1, 2), (3, 4))
foo{(1,2),(3,4),2,Int64}()

If you don’t care about 0.5, this works:

julia> struct foo{a, b, N, T}
           foo{a,b,N,T}(::NTuple{N, T}, ::NTuple{N, T}) where a where b where N where T = new()
       end

julia> foo(a, b) = foo{a, b, length(a), eltype(a)}(a, b)
foo

julia> foo((1, 2), (3, 4))
foo{(1, 2),(3, 4),2,Int64}()

Does anyone know whether the four where can somehow be reduced? Answering my own question:

julia> struct foo{a, b, N, T}
           foo{a,b,N,T}(::NTuple{N, T}, ::NTuple{N, T}) where {a, b, N, T} = new()
       end

#3

Thanks @mauro3. Just a question: what is the difference in the inner constructor syntax between

(::Type{foo{a,b,N,T}}){a,b,N,T}(::NTuple{N, T} ....

and

 foo{a,b,N,T}(::NTuple{N, T} ...

in your first and second code blocks?

Thanks!


#4

The first one adds a method for foo{a,b,N,T} (i.e. all type parameter specified) and can work on both 0.5 and 0.6 without depwarn. The second one adds a method for foo and will raise an depwarn on 0.6. If you don’t care about 0.5 compatibility, you can just follow the depwarn.

Also note that in your original version, you defined an inner constructor that does NOT match N and T to the actual type.

julia> foo{1,1,10000,Int}((1.0,), (1.0,))
foo{1,1,10000,Int64}()