I created a struct and get an error while creating an instance of it. I have tried reading the Julia manual and other material but am unable to resolve the error.
Updated code:
In binaryheap.jl →
mutable struct BinaryHeap{T<:Real}
htype::string
heap::Vector{T}
BinaryHeap{T}(heaptype="min") where T = (heaptype != "min" || heaptype != "max") ? error("Invalid heap type") : new{T}(heaptype, Vector{T}(undef, 0))
end
BinaryHeap{T}() where T = BinaryHeap{T}("min", Vector{T}(undef, 0))
BinaryHeap{T}(v::Vector{T}) where T = BinaryHeap{T}("min", v)
In tests.jl →
module algods
include("binaryheap.jl")
export BinaryHeap
export push!, min, max
end
using algods
function test_heap()
minheap = algods.BinaryHeap{Integer}("min")
algods.push!(minheap, 10)
algods.push!(minheap, 8)
algods.push!(minheap, 12)
min(minheap)
end
test_heap()
I get the following error when I run this. Please help me understand how I go about this and what the underlying idea is. Thank you.
WARNING: replacing module algods.
ERROR: LoadError: LoadError: TypeError: in BinaryHeap, in type definition, expected Type, got a value of type typeof(string)
Stacktrace:
[1] top-level scope
@ ~/projects/algods/binaryheap.jl:1
[2] include(mod::Module, _path::String)
@ Base ./Base.jl:386
[3] include(x::String)
The constructors using new must be inside the struct. (I didn’t test to see if that is the only problem)
Yet, they are most commonly used if there is an ambiguity with the default constructor, which is not the case there. It is more common to use, outside the struct, things like
struct MyType{T}
x::T
y::T
end
MyType(x::T) where T = MyType{T}(x,2*x)
I think you wanted htype::String, lower-case string is a function not a type.
Also, heaptype != "min" || heaptype != "max" is precisely false, maybe you wanted &&.
Then it runs:
julia> mutable struct BinaryHeap{T<:Real}
htype::String
heap::Vector{T}
BinaryHeap{T}(heaptype="min") where T = (heaptype != "min" && heaptype != "max") ? error("Invalid heap type") : new(heaptype, Vector{T}(undef, 0))
end
julia> BinaryHeap{Int}() # now runs
BinaryHeap{Int64}("min", Int64[])
julia> methods(BinaryHeap{Int}) # default has already made a method with 0 args
# 2 methods for type constructor:
[1] BinaryHeap{T}() where T in Main at REPL[8]:4
[2] BinaryHeap{T}(heaptype) where T in Main at REPL[8]:4
julia> methods(BinaryHeap)
# 0 methods for type constructor:
But the point of inner constructors is to make sure there is no other way to make the struct, except through them. Your last method tries to do that, and it fails. It’s trying to call what would be one of the default constructors had you not provided an inner constructor. It could instead construct & then mutate, but probably there are better ways.
julia> BinaryHeap{T}(v::Vector{T}) where T = BinaryHeap{T}("min", v)
julia> BinaryHeap{Int}([1,2,3])
ERROR: MethodError: no method matching BinaryHeap{Int64}(::String, ::Vector{Int64})