Denis Koroskin Wrote: > On Fri, 12 Dec 2008 19:32:03 +0300, Zoran Isailovski > <[email protected]> wrote: > > > I'm an experienced C#, Java and Python programmer, and have employed > > closures (and C# delegates) upon numerous occasions. While experimenting > > with D closures and delegates, I was stroke by a phenomenon I cannot > > explain. Here's the code: > > > > module closures01; > > > > import std.stdio; > > > > alias int delegate(int arg) Handler; > > > > Handler incBy(int n) > > { > > return delegate(int arg){ return arg + n; }; > > } > > > > Handler mulBy(int n) > > { > > return delegate(int arg){ return arg * n; }; > > } > > > > void test1() > > { > > writefln("\ntest1:\n----------------------------------------"); > > int x = 10, y; > > y = mulBy(3)(x); writefln("%d * 3 -> %d", x, y); > > y = mulBy(4)(x); writefln("%d * 4 -> %d", x, y); > > y = incBy(2)(x); writefln("%d + 2 -> %d", x, y); > > } > > > > void test2() > > { > > writefln("\ntest2:\n----------------------------------------"); > > int x = 10, y; > > Handler times3 = mulBy(3); > > Handler times4 = mulBy(4); > > Handler plus2 = incBy(2); > > y = times3(x); writefln("%d * 3 -> %d", x, y); > > y = times4(x); writefln("%d * 4 -> %d", x, y); > > y = plus2(x); writefln("%d + 2 -> %d", x, y); > > } > > > > public void run() > > { > > test1(); > > test2(); > > } > > > > /* **************************************** * > > * Compiled with: Digital Mars D Compiler v1.030 > > * > > * (Unexplainable) program output: > > test1: > > ---------------------------------------- > > 10 * 3 -> 30 > > 10 * 4 -> 40 > > 10 + 2 -> 12 > > > > test2: > > ---------------------------------------- > > 10 * 3 -> 20 > > 10 * 4 -> 42846880 > > 10 + 2 -> 4284698 > > > > * **************************************** */ > > > > What goes wrong??? > > I'd say that it works as expected and here is why. > > First of all, there are two types of closures: static and dynamic > closures. > Closures work by having a hidden pointer to function frame where all local > variables are stored. > > When a static closure is created, all the function local variables are > stored on stack. > It has an advantage that no memory allocation takes place (fast). > It has a disadvantage that once the delegate leaves the scope, it becomes > invalid since variables were stored on stack and the stack is probably > overwritten (unsafe). > > Dynamic closure allocates memory in a heap and all the local variables are > placed there. > It has a disadvantage that memory is allocated for dynamic closure (might > be slow if dynamic closure are created often). > It has an advantage that dynamic closure may leave the scope, i.e. you may > save it and call whenever you want. > > D1 support static closures only! That's why your code doesn't work (in > test1 stack is still valid, but in test2 stack gets overwritten) > D2 has support for dynamic closures. Just try it - your sample works as is.
An addition: Given the complexness of the criteria when a closure works and when not, I would vote for a compiler error on inappropriate closures usage. (In Java, closures cannot handle mutable values on the stack, so it's an error for a method to return a closure that refers to a non-final argument.)
