Full closures for D

Walter Bright newshound1 at digitalmars.com
Fri Nov 2 14:03:59 PDT 2007


D 2.007 brings full closures to D. I was tired of D being denigrated for 
not having "real" closures.

Here are some test cases for it, so you can see what it does:
-------------------------------------------

struct S { int a,b,c,d; }

alias int delegate() dg_t;
alias int delegate(int) dg1_t;

void fill()
{
     int[100] x;
}

/************************************/

dg_t foo()
{
     int x = 7;

     int bar()
     {
	return x + 3;
     }

     return &bar;
}

void test1()
{
     dg_t dg = foo();
     fill();
     printf("bar = %d\n", dg());
     assert(dg() == 10);
}

/************************************/

dg_t foo2()
{
     dg_t abc()
     {
	int x = 7;

	int bar()
	{
	    return x + 3;
	}

	return &bar;
     }

     return abc();
}

void test2()
{
     dg_t dg = foo2();
     fill();
     printf("bar = %d\n", dg());
     assert(dg() == 10);
}

/************************************/

dg_t foo3()
{
     dg_t abc(int x)
     {
	int bar()
	{
	    return x + 3;
	}

	return &bar;
     }

     return abc(7);
}

void test3()
{
     dg_t dg = foo3();
     fill();
     printf("bar = %d\n", dg());
     assert(dg() == 10);
}

/************************************/

dg_t foo4()
{   S s;

     s = S(4,5,6,7);

     dg_t abc(S t)
     {
	int bar()
	{
	    return t.d + 3;
	}

	return &bar;
     }

     return abc(s);
}

void test4()
{
     dg_t dg = foo4();
     fill();
     printf("bar = %d\n", dg());
     assert(dg() == 10);
}

/************************************/

void test5()
{   int x = 7;

     dg_t abc(ref int y)
     {
	int bar()
	{   y += 4;
	    return y + 3;
	}

	return &bar;
     }

     dg_t dg = abc(x);
     fill();
     assert(x == 7);
     auto i = dg();
     assert(x == 11);
     assert(i == 14);

     x = 8;
     i = dg();
     assert(x == 12);
     assert(i == 15);
}

/************************************/

void test6()
{   int x = 7;

     dg_t abc(out int y)
     {
	int bar()
	{   y += 4;
	    return y + 3;
	}

	return &bar;
     }

     dg_t dg = abc(x);
     fill();

     assert(x == 0);
     auto i = dg();
     assert(x == 4);
     assert(i == 7);

     x = 8;
     i = dg();
     assert(x == 12);
     assert(i == 15);
}

/************************************/

void test7()
{   int[3] a = [10,11,12];

     dg_t abc(int[3] y)
     {
	int bar()
	{   y[2] += 4;
	    return y[2] + 3;
	}

	return &bar;
     }

     dg_t dg = abc(a);
     fill();

     assert(a[2] == 12);
     auto i = dg();
     assert(a[2] == 16);
     assert(i == 19);
}

/************************************/

void test8()
{   S s = S(7,8,9,10);

     dg_t abc(ref S t)
     {
	int bar()
	{   t.d += 4;
	    return t.c + 3;
	}

	return &bar;
     }

     dg_t dg = abc(s);
     fill();

     assert(s.d == 10);
     auto i = dg();
     assert(s.d == 14);
     assert(i == 12);
}

/************************************/

S foo9(out dg_t dg)
{   S s1 = S(7,8,9,10);

     dg_t abc()
     {
	int bar()
	{   s1.d += 4;
	    return s1.c + 3;
	}

	return &bar;
     }

     dg = abc();
     return s1;
}

void test9()
{   dg_t dg;

     S s = foo9(dg);
     fill();
     assert(s.a == 7);
     assert(s.b == 8);
     assert(s.c == 9);
     assert(s.d == 10);

     auto i = dg();
     assert(s.d == 10);
     assert(i == 12);
}

/************************************/

dg_t foo10()
{
     dg_t abc()
     {
	int x = 7;

	int bar()
	{
	    int def()
	    {
		return x + 3;
	    }
	    return def();
	}

	return &bar;
     }

     return abc();
}

void test10()
{
     dg_t dg = foo10();
     fill();
     printf("bar = %d\n", dg());
     assert(dg() == 10);
}


/************************************/

dg_t foo11()
{
     int x = 7;

     class T
     {
	int bar()
	{
	    return x + 3;
	}
     }

     T t = new T;

     return &t.bar;
}

void test11()
{
     dg_t dg = foo11();
     fill();
     printf("bar = %d\n", dg());
     assert(dg() == 10);
}

/************************************/

dg_t foo12()
{
     int x = 7;

     class T
     {
	int bar()
	{
	    return x + 3;
	}

	int xyz()
	{
	    return bar();
	}
     }

     T t = new T;

     return &t.xyz;
}

void test12()
{
     dg_t dg = foo12();
     fill();
     printf("bar = %d\n", dg());
     assert(dg() == 10);
}

/************************************/

dg_t foo13()
{
     int x = 7;

     class T
     {
	int xyz()
	{
	    int bar()
	    {
		return x + 3;
	    }

	    return bar();
	}
     }

     T t = new T;

     return &t.xyz;
}

void test13()
{
     dg_t dg = foo13();
     fill();
     printf("bar = %d\n", dg());
     assert(dg() == 10);
}


/************************************/

dg_t foo14()
{
     class T
     {
	int xyz()
	{   int x = 7;

	    int bar()
	    {
		return x + 3;
	    }

	    return bar();
	}
     }

     T t = new T;

     return &t.xyz;
}

void test14()
{
     dg_t dg = foo14();
     fill();
     printf("bar = %d\n", dg());
     assert(dg() == 10);
}

/************************************/

dg_t foo15()
{
     class T
     {	int x = 7;

	int xyz()
	{
	    int bar()
	    {
		return x + 3;
	    }

	    return bar();
	}
     }

     T t = new T;

     return &t.xyz;
}

void test15()
{
     dg_t dg = foo15();
     fill();
     printf("bar = %d\n", dg());
     assert(dg() == 10);
}

/************************************/

dg_t foo16()
{   int a = 5;

     class T
     {	int x = 7;

	int xyz()
	{   int y = 8;
	    int bar()
	    {
		return a + x + y + 3;
	    }

	    return bar();
	}
     }

     T t = new T;

     return &t.xyz;
}

void test16()
{
     dg_t dg = foo16();
     fill();
     printf("bar = %d\n", dg());
     assert(dg() == 23);
}

/************************************/

dg_t foo17()
{   int a = 5;

     class T
     {	int x = 7;

	dg_t xyz()
	{   int y = 8;

	    int bar()
	    {
		return a + x + y + 3;
	    }

	    return &bar;
	}
     }

     T t = new T;

     return t.xyz();
}

void test17()
{
     dg_t dg = foo17();
     fill();
     printf("bar = %d\n", dg());
     assert(dg() == 23);
}

/************************************/

dg_t dg18;

void bar18()
{   int a = 7;
     int foo() { return a + 3; }

     dg18 = &foo;
     int i = dg18();
     assert(i == 10);
}

void test18()
{
     bar18();
     fill();
     int i = dg18();
     assert(i == 10);
}

/************************************/

void abc19(void delegate() dg)
{
     dg();
     dg();
     dg();
}

struct S19
{
     static S19 call(int v)
     {
	S19 result;

	result.v = v;
	void nest()
	{
	    result.v += 1;
	}
	abc19(&nest);
	return result;
     }
     int a;
     int v;
     int x,y,z;
}

int foo19()
{
    auto s = S19.call(5);
    return s.v;
}

void test19()
{
     int i = foo19();
     printf("%d\n", i);
     assert(i == 8);
}

/************************************/

int main()
{
     test1();
     test2();
     test3();
     test4();
     test5();
     test6();
     test7();
     test8();
     test9();
     test10();
     test11();
     test12();
     test13();
     test14();
     test15();
     test16();
     test17();
     test18();
     test19();

     printf("Success\n");
     return 0;
}



More information about the Digitalmars-d mailing list