www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - workaround for closure problem needed

reply mandel <foo bar.com> writes:
Hi,

I have a problem with closures and D 1.024.
D2 does have full closure support, but I have to stick with D1
for now.

Problem: variable "state" changes silently when the anonymous
function goes out of the scope of function filter.
Therefore the program does print out "item" only once.

My question is if there is a workaround ("static state" wouldn't be thread
safe)?

import tango.io.Stdout;
import tango.util.collection.iterator.FilteringIterator;
import tango.util.collection.iterator.ArrayIterator;
import tango.util.collection.model.Iterator;

class A
{
        uint getState() { return 0; }
}

Iterator!(A) filter(Iterator!(A) iter)
{
        uint state = 0;
        return new FilteringIterator!(A)( iter, (A item) { 
                return (item.getState == state); //should always return true
        });
}

void main(char[][] args)
{
        A[] aa = new A[10];
        foreach(inout a; aa) a = new A;
        
        auto array_iter = new ArrayIterator!(A)(aa);
        auto iter = filter(array_iter);
        
        foreach(a; iter)
        {
                Stdout("item").newline;
        }
}
Dec 26 2007
next sibling parent reply BCS <ao pathlink.com> writes:
Reply to Mandel,

 Hi,
 
 I have a problem with closures and D 1.024.
 D2 does have full closure support, but I have to stick with D1
 for now.
 Problem: variable "state" changes silently when the anonymous
 function goes out of the scope of function filter.
 Therefore the program does print out "item" only once.
 My question is if there is a workaround ("static state" wouldn't be
 thread safe)?
 
wrap the stuff (state + the local function) in a local struct, new off an instance at the top of the outer function, convert the outer function's access to "state" into "inst.state" and then replace the anon delegate with "&inst.fn". Crude and a bit ugly but it works. OTOH (WARNING: TOTAL HACK) if you want to go one step cheaper; state is 32bits, the same as a void*. struct Wrap { bool func(A item) { Cast c; c.pt = this; return (item.getState == c.ui); //should always return true } } union Cast {Wrap* pt; uint ui;} //to get dg; Cast c; c.ui = state; &c.pt.func; this works only if state is the only thing used and if it is not changed.
Dec 26 2007
parent reply =?ISO-8859-1?Q?=22J=E9r=F4me_M=2E_Berger=22?= <jeberger free.fr> writes:
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

BCS wrote:
 OTOH (WARNING: TOTAL HACK) if you want to go one step cheaper; state is
 32bits, the same as a void*.
 
Doesn't work on 64 bits platforms! Jerome - -- +------------------------- Jerome M. BERGER ---------------------+ | mailto:jeberger free.fr | ICQ: 238062172 | | http://jeberger.free.fr/ | Jabber: jeberger jabber.fr | +---------------------------------+------------------------------+ -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.7 (GNU/Linux) iD8DBQFHc1led0kWM4JG3k8RAsc9AJ43BIXYijvUF18cIBOVIZA1vvdO8QCeJb04 /12efoBUeayhetlzXHSfkTY= =1kBl -----END PGP SIGNATURE-----
Dec 26 2007
next sibling parent reply Bill Baxter <dnewsgroup billbaxter.com> writes:
Jérôme M. Berger wrote:
 -----BEGIN PGP SIGNED MESSAGE-----
 Hash: SHA1
 
 BCS wrote:
 OTOH (WARNING: TOTAL HACK) if you want to go one step cheaper; state is
 32bits, the same as a void*.
Doesn't work on 64 bits platforms!
Neither does DMD! ;-) --bb
Dec 27 2007
parent =?ISO-8859-1?Q?=22J=E9r=F4me_M=2E_Berger=22?= <jeberger free.fr> writes:
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Bill Baxter wrote:
 Jérôme M. Berger wrote:
 -----BEGIN PGP SIGNED MESSAGE-----
 Hash: SHA1

 BCS wrote:
 OTOH (WARNING: TOTAL HACK) if you want to go one step cheaper; state is
 32bits, the same as a void*.
Doesn't work on 64 bits platforms!
Neither does DMD! ;-)
True, but gdc works fine ;) Jerome - -- +------------------------- Jerome M. BERGER ---------------------+ | mailto:jeberger free.fr | ICQ: 238062172 | | http://jeberger.free.fr/ | Jabber: jeberger jabber.fr | +---------------------------------+------------------------------+ -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.7 (GNU/Linux) iD8DBQFHc42Ud0kWM4JG3k8RAsjoAKC7fjzX/apQuQS5cUh93b2DHoFK1QCgjpbk npzxg50ufCq1i6CIwgTqqk0= =agVx -----END PGP SIGNATURE-----
Dec 27 2007
prev sibling parent BCS <ao pathlink.com> writes:
Reply to Jérôme,

 -----BEGIN PGP SIGNED MESSAGE-----
 Hash: SHA1
 
 BCS wrote:
 
 OTOH (WARNING: TOTAL HACK) if you want to go one step cheaper; state
 is 32bits, the same as a void*.
 
Doesn't work on 64 bits platforms!
Actually it should work. You Just get 32bits of junk passed around that is ignored. The reverse is the one that wont work (ulong+64bit works but ulong+32bit fails) To be on the safe side the union should have: static assert((void*).sizeof >= Union.sizeof); and the other struct should have: static assert(0 == Struct.sizeof);
 Jerome
 - --
 +------------------------- Jerome M. BERGER ---------------------+
 |    mailto:jeberger free.fr      | ICQ:    238062172            |
 |    http://jeberger.free.fr/     | Jabber: jeberger jabber.fr   |
 +---------------------------------+------------------------------+
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1.4.7 (GNU/Linux)
 
 iD8DBQFHc1led0kWM4JG3k8RAsc9AJ43BIXYijvUF18cIBOVIZA1vvdO8QCeJb04
 /12efoBUeayhetlzXHSfkTY=
 =1kBl
-----END PGP SIGNATURE-----
Dec 27 2007
prev sibling parent mandel <foo bar.com> writes:
ok,

I was able to relax the contrains and solved the issue now by introducing a
helper class
to bind the value to the function.

I can drop the helper classes when my code can move over to D2.0
and make use of full closure support.
Dec 27 2007