I am making a type of my own called KeyVal
defined as below:
type KeyVal
first::Int
second::Float64
end
And I am trying to make an empty/or initialized at zero matrix that its elements are of type KeyVal
.
Normally with other types I do
myMat = zeros(KeyVal, (10,3))
But this will not work, because there is no zeros
defined for this composite type. So I try to define my own zeros function in the following way:
import Base.zeros
function zeros(KeyVal,dims)
if length(dims) > 1
n=dims[1]
m=dims[2]
temp = repeat([KeyVal(0,0.0)], outer=m*n)
temp = reshape(temp, (n,m))
return temp
elseif length(dims) == 1
n=dims[1]
temp= repeat([KeyVal(0,0.0)], outer=n)
temp = reshape(temp, (n))
return temp
end
end
This adds to the methods list of other previously defined zeros
.
But using it will generate errors:
myMat = zeros(KeyVal, (N,M))
MethodError: no method matching zero(::Type{KeyVal})
Closest candidates are:
.....
I am wondering whether I can resolve this in a way or maybe signal this in the type constructor so that any data structure that involves the type KeyVal
is initialized at (first = 0, second=0.0).
Previously I tried defining the matrix as :
myMat2 = Array{KeyVal,(N,M)}
This will create the matrix except all its elements are #undef
, and in this case I cannot access any of the elements of the myMat2
:
myMat2[1,1]
UndefRefError: access to undefined reference
You can create an uninitialized array of any type T
and dimension N
with
Array{T, N}(undef, dims...)
In the special case of one and two dimensional arrays, you can use the aliases Vector
and Matrix
, e.g.,
julia> m = Matrix{KeyVal}(undef, 2,2)
2×2 Array{KeyVal,2}:
#undef #undef
#undef #undef
You can then set the elements as usual, e.g.,
m[1,2] = KeyVal(1,2)
If it makes sense for your type to implement a zero
method, you can define
Base.zero(::Type{KeyVal}) = KeyVal(0,0)
and zeros
will work correctly
julia> zeros(KeyVal, (2,2))
2×2 Array{KeyVal,2}:
KeyVal(0,0.0) KeyVal(0,0.0)
KeyVal(0,0.0) KeyVal(0,0.0)
Warning:
zeros
uses fill!
which fills the array with copies of the same instance. Instead, use the comprehension below or an immutable type that doesn't contain references (isbits
is true). The latter approach is likely faster as well because the array can be stored as one continuous block of memory. In that case, you can also use fill(KeyVal(0,0), dims..)
directly instead of defining zero
. On 0.6, the new struct
keyword creates an immutable type by default.
Edit:
Another possibility is to use a comprehension
julia> m = [KeyVal() for i=1:3, j=1:2]
3×2 Array{KeyVal,2}:
KeyVal(0,0.0) KeyVal(0,0.0)
KeyVal(0,0.0) KeyVal(0,0.0)
KeyVal(0,0.0) KeyVal(0,0.0)
For convenience, I previously defined the outer constructor
KeyVal() = KeyVal(0,0)