Thursday, November 18, 2010

More Closure Fun

Here are some more closure test cases that work:

// Test the closures can be passed as parameters
def testClosureAsParam {
  var i = 0;
  callTenTimes(fn { i += 2; });
  Debug.assertEq(20, i);

  var s = StringBuilder();
  callTenTimes(fn { s.append("A"); });
  Debug.assertEq("AAAAAAAAAA", s.toString());
}

def callTenTimes(f:fn) {
  for i = 0; i < 10; ++i {
    f();
  }
}

// Test that nested closures work.
def testNestedClosures {
  let makeCounter = fn n:int -> fn -> int {
    return fn -> int {
      return n++;
    };
  };
  
  let c = makeCounter(2);
  Debug.assertEq(2, c());
  Debug.assertEq(3, c());
}

// Test that an inner closure can access a variable two levels out.
def testNestedClosures2 {
  var i = 0;
  let makeCounter = fn -> fn -> int {
    return fn -> int {
      return i++;
    };
  };

  let c = makeCounter();
  let d = makeCounter();

  Debug.assertEq(0, c());
  Debug.assertEq(1, c());
  Debug.assertEq(2, d());
  Debug.assertEq(3, d());
}

One thing that does not work yet is closure variables that are large structs or tuples - basically any local variable that is not an object reference or a primitive type. It shouldn't be hard to fix, however.

No comments:

Post a Comment