Zero-sized array of parametric types


#1

I have a Parametric type mytype{N}. One of its field is an SVector, and I want to have no pointers.

I use Vectors of mytype{N}. And of course, there comes a time when I have a vector v of length 0 of mytype{N}.

Then I do
v[:] = 0.
and boom:

MethodError: Cannot `convert` an object of type Float64 to an object of type mymodule.mytype
  This may have arisen from a call to the constructor mymodule.mytype(...),
  since type constructors fall back to convert methods.

I have written a Float64 to mytype{n} converter, but not a Float64 to mytype converter.

My interpretation: because the array is empty, the compiler is unable to determine N, tries to call a non-existent converter, and errors.

I have several questions:

  • The empty vector was built with data on N available (see below), and the compiler is not keeping track, isn’t that a weakness?
    variate(a::Vector) = [mytype{size(a,1)}(whatever) for i=1:size(a,1)]
  • why need a converter if zero data is to be converted, isn’t that a potential improvement of Julia?
  • If I wrote a Float64 to mytype converter, how does it look like (I don’t know N, right?). Is that the idiomatic way out?
  • I have my workaround (if length is zero, do not initialise…), but this jars with Julia’s natural elegance… Any suggestion?

#2

To me, it is a bit hard to understand the question. It is usually good if the code you provide is fully contained and can be run by pasting it in the REPL, i.e. give the definition of mytype how you construct it and the code you run for the error message to appear.


#3

OK, trying to reproduce the issue in a compact code, I realise the depth of my confusion, because I generate other errors I cannot handle. So, in Julia 6.0:

using     StaticArrays
mutable struct mytype{N}
    plain :: SVector{N,Float64}
end   

mytype{N}(x::Float64) =  mytype{N}([x for i = 1:N])
convert{N}(::Type{mytype{N}},x::Float64)           = mytype{N}(x)
promote_rule{N}(::Type{mytype{N}},::Type{Float64}) = mytype{N}

#v = [mytype{3}(Float64(i)) for i = 1:1]
v = [mytype{3}(Float64(i)) for i = 1:0

v[:] = 0.

This causes
LoadError: MethodError: Cannotconvertan object of type Float64 to an object of type mytype{3}
What’s wrong with my convertor?

Thanks beforehand

Philippe


#4

The code you posted doesn’t run as is on 0.6 (try copy paste it).


#5

Indeed I forgot a bracket on the second-last line, apologies. With that correction, I get the “convert” error.


#6

Nope, you get an error message about not importing convert.

Making a minimal effort to come up with a MWE that exhibits your problem often gets you help quicker.

In the form above, it is still hard to make sense of your code. What are you trying to do? Since v is an empty array of mytype (NB: please capitalize type names correcly), what should v[:] = 0 achieve?


#7

Interesting, thank you.

I understand that since I overload convert, I should import it, and that is going to be a source of trouble.

Interestingly, I do NOT get the same error message as you do, and that is queer.

The code is just intended to trigger a given error, it makes no sense in itself. Having general algorithms that need to cope with “zero operations” on empty array is not that uncommon…

So, running

import Base.convert,Base.promote_rule
using     StaticArrays
mutable struct mytype{N}
    plain :: SVector{N,Float64}
end   

mytype{N}(x::Float64) =  mytype{N}([x for i = 1:N])
convert{N}(::Type{mytype{N}},x::Float64)           = mytype{N}(x)
promote_rule{N}(::Type{mytype{N}},::Type{Float64}) = mytype{N}

#v = [mytype{3}(Float64(i)) for i = 1:1]
v = [mytype{3}(Float64(i)) for i = 1:0]

v[:] = 0.

gives me

WARNING: Method definition 
LoadError: MethodError: Cannot `convert` an object of type Float64 to an object of type StaticArrays.SArray{Tuple{3},Float64,1,3}
map(Any, Union{SA<:(StaticArrays.StaticArray{S, T, N} where N where T where S<:Tuple), AbstractArray{T, N} where N where T}...) in module StaticArrays at C:\Users\philippem\.julia\v0.6\StaticArrays\src\mapreduce.jl:10 overwritten in module StaticArrays at C:\Users\philippem\.julia\v0.6\StaticArrays\src\mapreduce.jl:10.
WARNING: static parameter N does not occur in signature for Type at untitled:8.
The method will not be callable.

So my failure to import was not the only problem…

Any thoughts?


#8

You also get:

WARNING: static parameter N does not occur in signature for Type at REPL[30]:1.
The method will not be callable.

from the mytype{N} function. Try:

mytype{N}(x::Float64) where {N} =  mytype{N}([x for i = 1:N])

#9

Ă…ĂĄĂĄĂĄh takk sĂĄ mycket!

My method was not syntactically correct, so I had no converter…

So simple. So I am going study the “where” manual in details…

Thank you!!!