I was wondering if it is possible in julia to assign a custom or existing type to a variable without calling it's constructor.
Something similar to a forward declaration of a class in c++.
Here is an example of what I intend to achieve:
type foo
a
end
#custom type
a = foo
b = foo
#julia type, force c to be of type Int
c = Int
a.a = 5.5
b.a = 4.5
c = 6
Edit To clarify my question:
In C++ or Fortran it is common coding practice to declare a variable at some point for later usage.
I don't recall the correct Fortran syntax but in C++ you would write something like:
class foo;
class bar;
int a;
class foo{
private:
bar myBar;
public:
foo(int a){ myBar( a ); }
}
class bar{
public:
bar(int a){
std::cout << a << std::endl;
}
}
a = 3;
foo( a );
The advantage of this code structure is that it allows you to define objects / types / variables before you use them.
In computer programming, a forward declaration is a declaration of an identifier (denoting an entity such as a type, a variable, a constant, or a function) for which the programmer has not yet given a complete definition.
The main rule is that you can only forward-declare classes whose memory layout (and thus member functions and data members) do not need to be known in the file you forward-declare it. This would rule out base classes and anything but classes used via references and pointers. Almost.
Generally you would include forward declarations in a header file and then include that header file in the same way that iostream is included.
A struct (without a typedef) often needs to (or should) be with the keyword struct when used. struct A; // forward declaration void function( struct A *a ); // using the 'incomplete' type only as pointer. If you typedef your struct you can leave out the struct keyword.
You can do variable declaration but not in the global scope; these are the constructs in Julia that introduce a new scope:
Certain constructs in the language introduce scope blocks, which are regions of code that are eligible to be the scope of some set of variables. The scope of a variable cannot be an arbitrary set of source lines; instead, it will always line up with one of these blocks. The constructs introducing such blocks are:
- function bodies (either syntax)
- while loops
- for loops
- try blocks
- catch blocks
- finally blocks
- let blocks
- type blocks.
Notably missing from this list are begin blocks and if blocks, which do not introduce new scope blocks.
You can optionaly use type declarations:
julia> x
ERROR: UndefVarError: x not defined
julia> x::Int
ERROR: UndefVarError: x not defined
julia> begin x end # still in global scope
ERROR: UndefVarError: x not defined
julia> begin x::Int end
ERROR: UndefVarError: x not defined
julia> let x end # local scope
julia> let x; x end
ERROR: UndefVarError: x not defined
Notice that Julia will try to convert the value to the specified type:
julia> let
x::Int # declare variables
y::Float64 = 7 # converts (if possible)
x = y # converts (if possible)
x, y
end
(7, 7.0)
julia> function foo(x, y)
x::Int
y::Float64
z # Any
# there must be assignment for conversion to happen
x, y = x, y
z = 5im
x, y, z
end
foo (generic function with 1 method)
julia> foo(3.0, 7)
(3,7.0,0 + 5im)
julia> type Foo{T<:Number}
x::T
end
julia> type Bar
x
end
julia> immutable Baz
a
b
c
end
julia> import Base.convert
julia> convert{T<:Number}(::Type{Foo{T}}, x::Number) = Foo(T(x))
convert (generic function with 535 methods)
julia> convert(::Type{Bar}, x) = Bar(x)
convert (generic function with 536 methods)
julia> convert(::Type{Baz}, xs::NTuple{3}) = Baz(xs...)
convert (generic function with 537 methods)
julia> let
# decalre variables:
a::Foo{Int}
b::Foo{Float64}
c::Bar
d::Baz
e::Int
# assign values:
e = 42
a = e
b = e
c = string(e)
d = 'a', e, "test"
[a, b, c, d]
end
4-element Array{Any,1}:
Foo{Int64}(42)
Foo{Float64}(42.0)
Bar("42")
Baz('a',42,"test")
julia>
It seems to me that what you want to do is to create an instance of a type without specifying the contents, and then fill it in later. This is possible to do by creating a constructor that leaves some fields uninitialized:
type Foo
a
# inner constructor that leaves all fields uninitialized
Foo() = new()
end
a = Foo()
b = Foo()
a.a = 5.5
b.a = 4.5
By giving fewer arguments to new
in the inner constructor than the type had fields, the last ones become uninitialized. It is an error to read an uninitialized field before it has been assigned a value.
Is this what you were after?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With