// capturing closures in lists: var f = funct() { var y = 5; var x = @[ funct() print y, funct() y = y + 1 ]; :result = x; }; //expect:5.0 f()[0](); f()[1](); //expect:6.0 f()[0](); // capturing the result of a function: var f2 = funct() { var x = { @f2 :result = funct() { print :f2; }; }; x = 5; }; //expect:5.0 f2()(); // oop: constructors, getters, setters var newAnimal = funct(species, color) { var species = species; // copy it so that it's mutable, if args ever get immutable var animal = @{ "getSpecies" = funct() :result = species, "setSpecies" = funct(newSpecies) species = newSpecies, "getColor" = funct() :result = color, // this captures an argument directly }; :result = animal; }; var horse1 = newAnimal("horse", "brown"); var horse2 = newAnimal("horse", "white"); var turtle = newAnimal("turtle", "brown"); //expect:horse print horse1["getSpecies"](); horse1["setSpecies"]("zebra"); //expect:zebra print horse1["getSpecies"](); //expect:brown print horse1["getColor"](); //expect:horse print horse2["getSpecies"](); //expect:white print horse2["getColor"](); //expect:turtle print turtle["getSpecies"](); // closure examples from craftinginterpreters // 1: var makeClosure = funct(value) { var closure = funct() { print value; }; :result = closure; }; var doughnut = makeClosure("doughnut"); var bagel = makeClosure("bagel"); //expect:doughnut doughnut(); //expect:bagel bagel(); // 2: (multi level closures) var outer = funct() { var x = "value"; var middle = funct() { var inner = funct() { print x; }; print "create inner closure"; :result = inner; }; print "return from outer"; :result = middle; }; //expect:return from outer var mid = outer(); //expect:create inner closure var in = mid(); //expect:value in(); // 3: (mixed multi level closures) outer = funct() { var a = 1; var b = 2; var result; var middle = funct() { var c = 3; var d = 4; var inner = funct() { print a + c + b + d; }; result = inner; }; :result = result; }; //expect:10.0 outer()(); // 4: manipulation of vals from closures outer = funct() { var x = "before"; var inner = funct() { x = "assigned"; }; inner(); print x; }; //expect:assigned outer(); // 5: get/setters using globals var globalSet; var globalGet; var main5 = funct() { var a = "initial"; var set = funct() { a = "updated"; }; var get = funct() { print a; }; globalSet = set; globalGet = get; }; main(); globalGet(); //expect:initial globalSet(); globalGet(); //expect:updated // 6: multiple upvalues in a simple scope { var a = 1; f = funct() { print a; }; var b = 2; g = funct() { print b; }; var c = 3; h = funct() { print c; }; print f(); print g(); print h(); //expect:1 //expect:2 //expect:3 }; // bonus: the last one with a list twist var bonus = funct() { var a = 1; f = funct() { print a; }; var b = 2; g = funct() { print b; }; var c = 3; h = funct() { print c; }; :result = @[f, g, h]; }; bonus = bonus(); bonus[2](); bonus[0](); bonus[1](); //expect:3 //expect:1 //expect:2