type-stable way to get primary type

188 views
Skip to first unread message

Mauro

unread,
Apr 21, 2015, 4:34:18 PM4/21/15
to julia...@googlegroups.com
I have a parameterized type and want to get the primary-type. For
example, I got

a = Array{Int,2}

is there a type-stable way to get Array? This is non-type stable:

f(t::Type) = t.name.primary

as the inferred return type is Type.

This does not work:

f{T, S}(::Type{T{S...}}) = T

Any ideas? Thanks, M

Jameson Nash

unread,
Apr 21, 2015, 4:56:48 PM4/21/15
to julia...@googlegroups.com
Your question presupposes that you can write useful generic code with the return result, but does not provide any context on your problem. When a similar question was asked previously on the mailing list, I recall pointing out that the code the author was attempting to write was not going to function as intended. Perhaps you can provide some more context?

The observation that I am making is that you cannot arbitrarily pick apart a type and expect everything to line up afterwards. For example, it is possible to have the following:
abstract AbstractTy{A,B}
type Ty1 <: AbstractTy{Int, Float64} end
type Ty2{B,A} <: AbstractTy{A,B} end

So you can't generically reconstruct some arbitrary subtype by some generic rearrangement of its type parameters.

Mauro

unread,
Apr 22, 2015, 4:19:16 AM4/22/15
to julia...@googlegroups.com
Thanks Jameson and here the context:

# Initializes an array which has a's container but b's eltype
function f(a::AbstractVector, b::AbstractVector)
Eb = eltype(b) # this is type-stable
Ca = typeof(a).name.primary # this is not type-stable
return Ca(Eb, 5) # assumes Ca supports the normal Array constructor
end

The last line would probably better use copy+convert but for that I
still need to make Ca{Eb,1}. Note that Ca is always a leaftype and I
don't want to climb the type hierarchy, so I think your remark about the
subtypes does not apply.

Here the typed code:
julia> @code_warntype f([1,2], [1.])
Variables:
a::Array{Int64,1}
b::Array{Float64,1}
Eb::Type{Float64}
Ca::Type{T} # <---

Body:
begin # none, line 3:
Eb = Float64 # line 4:
Ca = (top(getfield))((top(getfield))(typeof(a::Array{Int64,1})::Type{Array{Int64,1}},:name)::TypeName,:primary)::Type{T} # line 5:
return (Ca::Type{T})(Eb::Type{Float64},5)::Any
end::Any

Thanks!

Mauro

unread,
Apr 22, 2015, 6:22:49 AM4/22/15
to julia...@googlegroups.com
A generated function works:

@generated function f(a::AbstractVector, b::AbstractVector)
Eb = eltype(b)
Ca = a.name.primary
return :($Ca($Eb, 5))
end

julia> @code_warntype f([1,2], [1.])
Variables:
a::Array{Int64,1}
b::Array{Float64,1}

Body:
begin
return (top(ccall))(:jl_alloc_array_1d,$(Expr(:call1, :(top(apply_type)), :Array, Float64, 1)),$(Expr(:call1, :(top(svec)), :Any, :Int)),Array{Float64,1},0,5,0)::Array{Float64,1}
end::Array{Float64,1}

But is there a way to do this type-stabally in 0.3 too?

Tim Holy

unread,
Apr 22, 2015, 9:17:27 AM4/22/15
to julia...@googlegroups.com
As Jeff says...this is why `similar` exists.

--Tim

Andreas Noack

unread,
Apr 22, 2015, 9:43:22 AM4/22/15
to julia...@googlegroups.com
This problem is quite common in the LinAlg code. We have two type of definitions to handle the conversion of the element types. First an idea due to Jeff as implemented in


and


These create maybe-aliased objects which can be problem in the destructive linalg functions so therefore Simon Kornblith invented copy_oftype which you can see example of here


Notice that it requires two method definitions for each type.

Steven G. Johnson

unread,
Apr 22, 2015, 10:26:43 AM4/22/15
to julia...@googlegroups.com
As Tim says, you just want similar(a, eltype(b), 5) 

On Wednesday, April 22, 2015 at 6:22:49 AM UTC-4, Mauro wrote:
A generated function works:

(I'm starting to be very suspicious of every time someone suggests using a generated/staged function. It's too easy to turn this into a crutch; it's not a feature that should really come up in everyday usage.)

Mauro

unread,
Apr 22, 2015, 10:59:41 AM4/22/15
to julia...@googlegroups.com
Excellent, thanks to you all. `similar` is what I need (this puts the
burden on the type creator, which is fine by me ;-)
Reply all
Reply to author
Forward
0 new messages