6

The "yield" statement in python allows simple iteration from a procedure, and it also means that sequences don't need to be pre-calculated AND stored in a array of "arbitrary" size.

Is there a there a similar way of iterating (with yield) from a C procedure?

NevilleDNZ
  • 1,269
  • 12
  • 31
  • What the point in asking this question? You just wanted to answer it yourself to pump up your rating? It was on Reddit yesterday so I don't think there is a coincidence. So you get -1 for the question and -1 for the answer from me. – qrdl May 07 '09 at 07:18
  • You should only ask questions at SO. I appreciate your intention to share the knowledge but places like Reddit and Digg are more appropriate for this. I'll undo my downvotes as your mistake is unintentional. – qrdl May 07 '09 at 08:28
  • 4
    @qrdl This was handled a long time ago (http://stackoverflow.com/questions/2572) NevilleDNZ's behavior is not only acceptable, it is encouraged. You even get a badge for getting 3 up votes on an answer to your own question. This is a place for questions and answers, the fact that one person delivers both is not something to look down upon. – Chas. Owens May 08 '09 at 01:56
  • Whenever I find such cases, I do a copy-paste from the self-answer to a community-wiki owned answer, which can be chosen as "the" answer (since the question has been answered). – tzot May 08 '09 at 08:47

3 Answers3

6

Here follows a community-wiki copy of the self-answer, which can be chosen as "the" answer. Please direct up/downvotes to the actual self-answer

Here is the method I found:

    /* Example calculates the sum of the prime factors of the first 32 Fibonacci numbers */
#include <stdio.h>

typedef enum{false=0, true=1}bool;

/* the following line is the only time I have ever required "auto" */
#define FOR(i,iterator) auto bool lambda(i); yield_init = (void *)&lambda; iterator; bool lambda(i)
#define DO {
#define     YIELD(x) if(!yield(x))return
#define     BREAK return false
#define     CONTINUE return true
#define OD CONTINUE; }
/* Warning: _Most_ FOR(,){ } loops _must_ have a CONTINUE as the last statement. 
 *  *   Otherwise the lambda will return random value from stack, and may terminate early */

typedef void iterator; /* hint at procedure purpose */
static volatile void *yield_init;
#define YIELDS(type) bool (*yield)(type) = yield_init

iterator fibonacci(int n){
   YIELDS(int);
   int i;
   int pair[2] = {0,1};
   YIELD(0); YIELD(1);
   for(i=2; i<n; i++){
      pair[i%2] = pair[0] + pair[1];
      YIELD(pair[i%2]);
   }
}

iterator factors(int n){
  YIELDS(int); 
  int i;
  for(i=2; i*i<=n; i++){
    while(n%i == 0 ){
      YIELD(i);
      n/=i;
    }
  }
  YIELD(n);
}

main(){
    FOR(int i, fibonacci(32)){
        printf("%d:", i);
        int sum = 0;
        FOR(int factor, factors(i)){
            sum += factor;
            printf(" %d",factor);
            CONTINUE;
        }
        printf(" - sum of factors: %d\n", sum);
        CONTINUE;
    }
}

Got the idea from http://rosettacode.org/wiki/Prime_decomposition#ALGOL_68 - but it reads better in C

tzot
  • 92,761
  • 29
  • 141
  • 204
  • This seems pretty awesome, but is there any explanation on how it works. I'm getting very confused with the whole auto bool lambda statement. – parent5446 Apr 15 '12 at 03:48
  • OK, never mind. I think I understand. Basically it declares the actual loop being iterated with as a function and then calls that function within the iterator function. – parent5446 Apr 15 '12 at 03:53
3

I pull this URL out as a joke from time to time: Coroutines in C.

I think the correct answer to your question is this: there's no direct equivalent, and attempts to fake it probably won't be nearly as clean or easy to use.

Dan Olson
  • 22,849
  • 4
  • 42
  • 56
0

No.

Nice and short!

Daniel Earwicker
  • 114,894
  • 38
  • 205
  • 284