confusing (buggy?) closure behaviour

Denis Koroskin 2korden at gmail.com
Fri Dec 12 08:46:00 PST 2008


On Fri, 12 Dec 2008 19:32:03 +0300, Zoran Isailovski  
<dmd.zoc at spamgourmet.com> 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.


More information about the Digitalmars-d-learn mailing list