Path: utzoo!utgpu!jarvis.csri.toronto.edu!mailrus!tut.cis.ohio-state.edu!ucbvax!bloom-beacon!mcgill-vision!mouse From: mouse@mcgill-vision.UUCP (der Mouse) Newsgroups: comp.lang.c Subject: Re: Coroutines in C Message-ID: <1624@mcgill-vision.UUCP> Date: 28 Aug 89 08:24:39 GMT References: <5663@ficc.uu.net> <14281@haddock.ima.isc.com> <563@augean.OZ> <10109@csli.Stanford.EDU> Organization: McGill University, Montreal Lines: 46 In article <10109@csli.Stanford.EDU>, poser@csli.Stanford.EDU (Bill Poser) writes: > In article <5710@ficc.uu.net> peter@ficc.uu.net (Peter da Silva) writes: >> Generators in Smalltalk are implemented differently than in Icon. >> You set up methods for getting the first and next element of the >> sequence, and use instance variables (if necessary) to maintain >> state. This is more conventional, and wouldn't require coroutines. > I'm not sure I understand how this solves the problem. Using > instance variables is pretty much like using statics in C to store > the state information, but the real problem is in implementing the > method for getting the next element in the sequence. [...What's > needed is] the equivalent of the Icon "suspend" primitive, which > returns a value but saves the stack frame. Right. > Isn't the Smalltalk method of implementing generators just doing it > by hand as in the above C example, with instance variables playing > the role of statics? Doing a generator in C this way works fine - provided only one copy of each generator is active at once. Suppose we write a generator that returns numbers in sequence, from 0 up: generate_Z() { static int i = 0; return(i++); } This works fine if we use it in simple applications. But try to use two copies of it to drive two nested loops, for example, and you'll get a little surprise.... The `instance variable' approach, while not as nice as the Icon way, is nicer than using statics in C. (C can do this, but as far as I can see you need to fake instances: typedef struct generator_Z_state { int i; } ZZZ; /* typedef for brevity */ char *new_generator_Z() { struct ZZZ z; /* char * for data hiding */ z = (ZZZ *)malloc(sizeof(ZZZ)); z->i = 0; return((char *)z); } int generator_Z(state) char *state; { return(((ZZZ *)state)->i++); } destroy_generator_Z(state) char *state; { free(state); } which is a bit ugly, but sometimes necessary. This would of course be nicer in some other language, C++ for example, which is better suited to object-oriented coding.) der Mouse old: mcgill-vision!mouse new: mouse@larry.mcrcim.mcgill.edu