-
-
Notifications
You must be signed in to change notification settings - Fork 680
Open
btc-vision/assemblyscript
#1Labels
Description
I decide to start discussion about simple closure implementations.
Some obvious (and may be naive) implementation is using generation class context which I prefer to demonstrate in following example:
declare function externalCall(a: i32, b: i32): void;
function range(a: i32, b: i32, fn: (n: i32) => void): void {
if (a < b) {
fn(a);
range(a + 1, b, fn);
}
}
export function test(n: i32): void {
range(0, n, (i: i32) => {
externalCall(i, n); // capture n
});
}which transform to:
// generated
class ClosureContext {
fn: (ctx: usize, i: i32) => void;
n: i32; // captured var
// optinal "self: usize;" is closure instantiate inside instance class method
parent: ClosureContext | null = null;
}
// generated
function lambdaFn(ctx: usize, i: i32): void {
externalCall(i, changetype<ClosureContext>(ctx).n);
}
function range(a: i32, b: i32, ctx: usize): void {
if (a < b) {
changetype<ClosureContext>(ctx).fn(ctx, a); // replaced from "fn(a)";
range(a + 1, b, ctx);
}
}
export function test(n: i32): void {
// insert
let ctx = new ClosureContext();
ctx.fn = lambdaFn;
ctx.n = n;
//
range(0, n, changetype<usize>(ctx));
}Closure and ClosureContext will not generated when no one variable was captured and use usual anonym functions.
ClosureContext will not created when only this was captured. In this case ctx param use to pass this reference.
Other discussions: #563
@dcodeIO @jtenner @willemneal Let me know what you think about this?
svenallers, eugenesvk, samratarmas, Matiyeu, JairusSW and 7 morelastmjs, remorses, iddan, aminya, Qix- and 8 more