Skip to content

redesign constructors to allow uninitialized fields #30

@JeffBezanson

Description

@JeffBezanson

Currently we need to do ugly things to make circular references:

type MyType
  self::Union((),MyType)
  function MyType()
    v = new(())
    v.self = v
  end
end

That is really bad, both ugly and compiler-unfriendly. With the change, we'd have

type MyType
  self::MyType
  MyType() = (this.self = this)
end

For constructors inside the type block, this is supplied, and the type's static parameters will be visible as well. this will also be returned automatically, and using return in a constructor will be an error.
Here's what Rational would look like:

 type Rational{T<:Int} <: Real
     num::T
     den::T

     function Rational(n::Int, d::Int)
         # can use T here
         g = gcd(n,d)
         this.num = div(n,g)
         this.den = div(d,g)
         # this is returned implicitly
     end
 end

 Rational{T}(n::T, d::T) = Rational{T}(n,d)
 Rational(n::Int, d::Int) = Rational(promote(n,d)...)
 Rational(n::Int) = Rational(n,1)

Notice the constructor inside the type block is only usable given an instantiated version of the type, Rational{T}. An outside generic function Rational() is defined to do this for you. If there are no user-defined constructors, we can still provide the same default constructors we have now.

One downside to this is that we'll have to check each field access for uninitialized references, as we currently do for elements of pointer arrays.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions