213 lines
3.1 KiB
Plaintext
213 lines
3.1 KiB
Plaintext
// 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
|