Non-default Constructor


#1

I am having trouble with defining a non-default constructor. See code snippet below,

type AType
     a::Float64
end

type BType
    b::Float64
    Btype(a_type::AType)=new(a_var.a)
end

a_var=AType(5.0)
b_var=BType(a_var)

While trying to invoke the non-default constructor for BType I get an error that reads,

LoadError: MethodError: Cannot `convert` an object of type AType to an object of type BType
This may have arisen from a call to the constructor BType(...),

What am I doing wrong?

Thanks!


#2

You have a capitalization typo: Btype(a_type::AType)=new(a_var.a) should be BType


#3

Thanks!


#4

Also, should be a_type


#5

Actually, I was planning to ask a completely different question (got distracted by silly typos…)
The problem I encountered is trying to split the above code into to several modules.
Explicitly, I define AType and BType in A.jl and B.jl respectively and then construct BType from Atype in C.jl. See below,

A.jl

module A

export AType

type AType
     a::Float64
end

end

B.jl

module B

export BType
include("./A.jl")
using .A

type BType
    b::Float64
    BType(a_type::AType)=new(a_type.a)
end

end

and C.jl

module C

include("./A.jl")
include("./B.jl")

using .A
using .B

a_var=AType(5.0)
b_var=BType(a_var)

end

I get the following Error,

LoadError: MethodError: Cannot `convert` an object of type C.A.AType to an object of type C.B.BType
This may have arisen from a call to the constructor C.B.BType(...),
since type constructors fall back to convert methods.
 in C.B.BType(::C.A.AType) at ./sysimg.jl:53

I was basically trying to imitate C++ include system but I guess that doesn’t really work here.
I have noticed that including a module from an external file appends the current “namespace”, is the source of error? If so how can I avoid this behavior?


#6

Manage include explicitly and include each file only once.


#7

Thanks for the quick reply.

Just to make this more concrete, I have removed the include statements appearing in A.jl and B.jl ( I still keep them in C.jl). Now, running C.jl results in an error corresponding to the fact that module B doesn’t recognize module A:

LoadError: LoadError: UndefVarError: A not defined

How can I make module A visible in module B (or more generally to code in B.jl).


#8

You should do

# C.jl
module C

# A.jl
module A
# ...
end
# `using .A` if you want to bring exports into `C`'s scope

# B.jl
module B
using .A
# ...
end

end


#9

Thanks again for the quick reply!
I must be missing something very basic here…

Here is my revised code (in an attempt to follow your suggestions):

# A.jl
module A
export AType
type AType
     a::Float64
end
end
# B.jl
module B
export BType
using .A
type BType
    b::Float64
    BType(a_type::AType)=new(a_type.a)
end
end

and

# C.jl
module C
include("./A.jl")
using .A
a_var=AType(5.0)
include("./B.jl")
using .B
b_var=BType(a_var)
end

I still get an error, which as far as I understand is related to the visibility of “A” in “B”.

LoadError: LoadError: UndefVarError: A not defined
 in include_from_node1(::String) at ./loading.jl:488
 in include_from_node1(::String) at /Applications/Julia-0.5.app/Contents/Resources/julia/lib/julia/sys.dylib:?
 in include_string(::String, ::String) at ./loading.jl:441
 in include_string(::String, ::String) at /Applications/Julia-0.5.app/Contents/Resources/julia/lib/julia/sys.dylib:?
 in include_string(::Module, ::String, ::String) at /Users/snirgaz/.julia/v0.5/CodeTools/src/eval.jl:32
 in (::Atom.##61#64{String,String})() at /Users/snirgaz/.julia/v0.5/Atom/src/eval.jl:81
 in withpath(::Atom.##61#64{String,String}, ::String) at /Users/snirgaz/.julia/v0.5/CodeTools/src/utils.jl:30
 in withpath(::Function, ::String) at /Users/snirgaz/.julia/v0.5/Atom/src/eval.jl:46
 in macro expansion at /Users/snirgaz/.julia/v0.5/Atom/src/eval.jl:79 [inlined]
 in (::Atom.##60#63{String,String})() at ./task.jl:60
while loading /Users/snirgaz/Code/./B.jl, in expression starting on line 3
while loading /Users/snirgaz/Code/C.jl, in expression starting on line 5

Thanks!


#10

Sorry using ..A in B