Search code examples
pythonciteratorjitalgol68

Python style iterators in C


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?


Solution

  • 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