I got in a small argument at a meetup about R. Something about python being a BetterLanguage[tm] than R. One of the arguments was that python is better because the language has support for generators. This was an interesting moment because I definately agree that the way that generators work in python is great. I would even argue that there are parts in python that work better for many tasks than R might (and vise versa). But I wouldn't argue that R does not a very similar feature to generators in python, but they do require you to think differently.

Let's explore how this might work.

## Python Generator

Let's pretend we want to make a genator like this one from python work in R.

def infinite_generator():
i = 0
while True:
i += 1
yield i

gen = infinite_generator()
next(gen) #1
next(gen) #2
next(gen) #3


Note that the only reason that this works in python is because of the yield keyword. This causes the loop in the function to give control back to whatever called the function. This means that we can call next(gen) without having to worry about an infinite about of numbers filling up the memory on the machine. This is useful.

## R Generator-like-function

How would you build something like this in R? Actually, we can use a function.

infinite_generator <- function(){
i <- 0
function(){
i <<- i + 1
i
}
}

gen <- infinite_generator()
gen() #1
gen() #2
gen() #3


This might baffle you if you've never seen <<- before. Feel free to run the code to confirm that it works.

The reason why we got the generator to work is that the special assignment operator <<- allows you to update a value outside of the scope of the body of the function. This is a trick that effectively allows the function to carry along some state. Effectively every time we run the function the value of i gets updated and the scope will be contained to the calling of the function gen.

Python has a generator pattern that allows you to take values from an infitite list without the memory blowing up but R has an assignment mechanic that allows functions to do something very similar. Just like R does not have yield python does not have <<-.

You can go further with R if you really care about mocking python. Because it is such a functional language, you can even define a function to behave like yield from python. Youd be torturing the language a bit, but an example can be found here.

## Actually

After thinking about this, I was wondering if you can have a python function work in a similar way. Can we make a function that keeps track of some state?

Turns out: you can! After all, functions are objects, so you can assign state to a function. This is a freaky trick, but it works:

def another_generator():
another_generator.i = 0
def update():
another_generator.i += 1
return another_generator.i
return update

gen = another_generator()
gen()
gen()
gen()


I'm totally not suggesting this is good practice by the way. I'd recommender a proper python generator over a hacked python function.

## Conclusion

Different language may solve problems differently but just because a language does not follow a certain pattern does not mean that the language does not have a way to fix the problem.

If you're interested in an application of these functional generators: these generators can be used in deep learning in R (it's used to many images to neural networks without having all the images in memory). It actually used in the the R keras package. If you want to learn more about this, you can check out a book written by some of the fine folks behind Rstudio and the creator of Keras.