module Constructors { 
 
  // CONSTUCTOR BASICS 
 
  struct Wall { 
    width : int; 
    height : int; 
    area : int; 
  } 
 
  // define exception type 
  except ZeroSize{size : int} 
 
  // constructor functions can be defined for structs 
  // • once a constructor function is defined it is used for all construction of the type. 
  // • constructors functions must be defined in the same module that defines the type. 
  // • if a constructor function is private, then only the defining module can create the type. 
  // • the return type is the type being constructed.  within the scope of the constructor 
  //   the default constructor for the type will be used instead of the constructor  
  //   being defined. 
  constructor(width : int, height : int) : Wall => { 
    if (width == 0) { 
      throw ZeroSize(width); 
    } 
    if (height == 0) { 
      throw ZeroSize(height); 
    } 
    // NOTE: within the constructor function, the default constructor is used 
    return Wall(width, height, width * height); 
  } 
 
  fn test1() { 
    let w1 = Wall(4, 8);    // calls constructor to initialize Wall 
    let w2 = Wall(4, 0);    // constructor raises ZeroSize exception 
  } 
 
  // GENERIC CONSTRUCTORS 
 
  // constructors can be generic, for example if the fields are generic 
  // or the parameters to the constructor are generic. 
 
  // define exception used by Distance constructor 
  except UnitMissing{} 
 
  // define Distance struct with generic parameter T for distance 
  struct Distance{T} { 
    value : T; 
    units : string; 
  } 
 
  // Constructor for generic Distance struct with generic T parameter 
  constructor{T}(value : T, unit : string) : Distance{T} => { 
    if (unit == "") { 
      throw UnitMissing; 
    } 
    return Distance(value, unit); 
  } 
 
  fn test2() { 
    let d1 = Distance{int}(1, "feet");            // construct Distance with int type 
    let d2 = Distance{double}(2.0, "meters");     // construct Distance with double type 
 
    // since the compiler can infer the generic type, the following are equivalent to the above 
    let d3 = Distance(1, "feet");                 // construct Distance with int type 
    let d4 = Distance(2.0, "meters");             // construct Distance with double type 
  } 
}