module Pure { 
   
  // PURE FUNCTIONS 
 
  // A function is considered "pure" if all of the following are true: 
  // • it does not call any impure functions, other than those passed to it 
  // • it is not a closure 
  // • it does not use thread local variables 
  // 
  // Note that a function may be pure even if it accesses mutable types 
  // or has mutable types in it's signature. 
  //   
  // The compiler automatically classifies function implementations as 
  // pure or impure based on their implementation. 
  // 
  // Generic functions are evaluated at to their purity based on the 
  // specific types involved. 
  // 
  // External functions are considered impure by default but can be annotated 
  // with pure if the implementation meets the requirements. 
  // 
  // Function types are considered impure by default, but may be modified  
  // with the pure keyword.  A cast to a pure function type will fail 
  // if the function is not pure. 
 
  // define a row structure 
  struct Row { 
    values: string[]; 
  } 
 
  // define a query function for rows where the implementation must be pure 
  typedef QueryFn = pure fn(rows : Row[]) : Row[]; 
 
  // implement a query function that is pure 
  fn simple_query_fn(rows : Row[]) : Row[] => { 
    let new_rows : mut Row[] = []; 
    for (row in rows) { 
      if (new_rows.values[0] == "keep") { 
        new_rows.append(row); 
      } 
    } 
    return new_rows.take(); // convert mutable to immutable 
  } 
 
  fn test1() { 
    // cast query function to function type 
    let q = simple_query_fn::QueryFn; // ok: function meets pure requirements 
  } 
 
  // PURE INTERFACES 
 
  // Interfaces are considered impure by default, but can be annotated with 
  // pure to indicate that all methods must be pure. 
 
  // define an query interface that works on rows 
  pure interface Query { 
    query(rows : Row[]) : Row[]; 
  } 
 
  // define a simple query struct 
  struct SimpleQuery { 
    value: string; 
  } 
 
  impl Query { 
    query(this : SimpleQuery, rows : Row[]) : Row[] => { 
      let new_rows : mut Row[] = []; 
      for (row in rows) { 
        if (new_rows.values[0] == this.value) { 
          new_rows.append(row); 
        } 
      } 
      return new_rows.take(); // convert mutable to immutable 
    } 
  } 
 
  fn test2() { 
    // cast SimpleQuery to Query interaface 
    let q = SimpleQuery::Query; // ok: implementation meets requirements 
  } 
}