for this, I am sure you will have to use a static integer variable inside the iter function so that it has persistence between function calls. Test this small script in your C editor and and see if it suits your needs. Type a 1 to call the iter function, and any other integer to exit. The script behavior is similar to that of yield in Python.
#include <stdio.h>
int iterator_in_c(int stop_value){
int iter_value = 0;
static int counter = 0;
if (counter <= stop_value)
{
iter_value = counter;
counter += 1;
return iter_value;
}
else{
counter = 0;
return -1;
}
}
int main()
{
int number = 0;
int result = 0;
while(1){
printf("\nDo you want to call the function (1 = yes, any other to exit)? ");
scanf("%d", &number);
if(number == 1){
result = iterator_in_c(5);
printf("The value of result is: %d", result);
}
else{
printf("\nExiting the program. ");
break;
}
}
return 0;
}
I went ahead and generalized it a bit such that you can pass in any array as an argument. You can then obtain one of its values one at a time every time that the function is called. It is not as involved as the one in Python where you create a whole new variable and then iterate over it with the next() keyword, however. Note also that I am not raising an exception once ALL elements have been processed as Python does. I merely print a message that all the elements have been processed. If you’d like to raise an exception, modify it as you’d like.
Here it is included with a test code wrapper for testing convenience.
#include <stdio.h>
int iter_in_c(int *iter, int length){
static int index = 0;
if (index < length){
return iter[index++];
}
else{
return -1;
}
}
int main()
{
int number = 0;
int result = 0;
int values [] = {10, 20, 30, 40, 50};
while(1){
printf("\nDo you want to call the function (1 = yes, any other to exit)? ");
scanf("%d", &number);
if(number == 1){
result = iter_in_c(values, sizeof(values) / sizeof(values[0]));
if(result == -1)
{
printf("\n*** All values have been processed. ***\n");
}
else{
printf("The value of result is: %d", result);
}
}
else{
printf("\nExiting the program. ");
break;
}
}
return 0;
}
It isn’t hugely easy. Essentially gen_func has to return an extension type with a tp_iternext slot that gets the next value to be yielded.
You store the persistent state (i and a pointer to self in your case) on the extension type. When the iteration is done you return NULL from the function.
If you want it to look “perfectly” like a Python generator then you need more detail, but for the simple case that’s what you have to do.
class G1:
def get_iter(self):
yield 0
class G2:
def get_iter(self):
return Iter()
class Iter:
end = False
def __iter__(self):
return self
def __next__(self):
if self.end:
raise StopIteration
self.end = True
return 0
So in C, the approach is similar to G2. I was just wandering if there are any ways/tricks to follow something more similar to G1. I dont have much hope for it, but just double checking to make sure I am not missing something.