Of Generators and Chainlets

The behaviour of all basic building blocks of chainlet is modeled after generators. In turn, generators integrate seamlessly into chains.

Generators as data providers

As with functions, a chainlink can be created by promoting a generator using genlet(). Using a genlet() is suitable when you need to preserve state between steps.

Simply decorate a regular generator, which

  • produces the desired results via yield.
>>> from chainlet import genlet
>>> import random
>>>
>>> @genlet(prime=False)  # <= do not prime producing generators!
... def pseudo_random_trigger(chance_slope=0.1):          # (1)
...     misses = 1  # number of times no hit was triggered
...     while True:                                         # (2)
...         if misses * chance_slope > random.random():
...             yield True                                  # (3)
...             misses = 1
...         else:
...             yield False                                 # (3)
...             misses += 1

The core of a genlet() is a regular generator: it requires no additional argument to receive data (1), can loop and repeat arbitrarily (2), and provides multiple results via yield (3). A genlet() can also safely hold persistent resources - for example an open file in a with context.

Interlude: If it quacks like a generator…

Our new genlet() behaves practically the same as a regular generator. To use it, you must instantiate it, which allows you to fill in all parameters.

>>> chain = pseudo_random_trigger()  # use default ``chance_slope=0.1``
>>> chain = pseudo_random_trigger(0.2)

The genlet() is fully compliant with the generator protocl. In other words, you can still use your genlet() as if it were just a generator:

>>> for is_hit in pseudo_random_trigger(0.2):
...     print('Hit!' if is_hit else 'Miss')
...     if is_hit:
...         break