paulfitz / cosmicos

Sending the lambda calculus into deep space
https://cosmicos.github.io/
GNU General Public License v2.0
134 stars 8 forks source link

Feature request: Fritz needs finite and infinite generators #34

Open joha2 opened 2 years ago

joha2 commented 2 years ago

In Python there exist generators which serve as finite or infinite data sources.


def finite_generator(): 
     yield "a" 
     yield "b" 
     yield "c" 

How to use:

>>> s = finite_generator()                                                                                                                                               
>>> next(s)                                                                                                                                                             
'a'
>>> next(s)                                                                                                                                                             
'b'
>>> next(s)                                                                                                                                                             
'c'
>>> next(s)                                                                                                                                                             
---------------------------------------------------------------------------
StopIteration                             Traceback (most recent call last)

Or infinite

# see https://yewtu.be/watch?v=5jwV3zxXc8E
def nats(n):
     yield n
     yield from nats(n + 1)

nats_stream = nats(0)

Usage:

>>> next(nats_stream)
0
>>> next(nats_stream)
1
>>> next(nats_stream)
2
>>> next(nats_stream)
3

This representation of natural numbers could be used as constructive implementation of sequences in maths. (E.g. for the mentioned continued fractions.) From there one can use:

def partial_sum(generator): 
     mysum = 0. 
     for v in generator: 
         mysum += v 
         yield mysum 

arctan_series_times_4 = (4*(-1)**n/(2*n+1) for n in nats(0)) # 4*(1, -1/3, 1/5, ....)
pi_approx = partial_sum(arctan_series_times_4) # 4*(1 - 1/3 + 1/5 - ....)

to calculate an approximation of pi. Using pi_approx:

>>> next(pi_approx)
4.0
>>> next(pi_approx)
2.666666666666667
>>> next(pi_approx)
3.466666666666667
>>> next(pi_approx)
2.8952380952380956
>>> next(pi_approx)
3.3396825396825403
>>> next(pi_approx)
2.9760461760461765
>>> next(pi_approx)
3.2837384837384844
>>> next(pi_approx)
3.017071817071818
>>> next(pi_approx)
3.2523659347188767

This is a horribly slow convergent series. One can use other series representation or the continued fractions to accelerate it. The point is: In the message one could write something like

intro pi;
(< (abs (- pi (next pi_approx))) (frac 2 1));
(< (abs (- pi (next pi_approx))) (frac 1 2));
(< (abs (- pi (next pi_approx))) (frac 1 3));
...

which shows the listener that pi is a constant which is approximated better with every step of (next pi_approx). In some sense, one shows the limit in a manual way. :-) From this point, it is possible to show the listener irrational numbers as limits of certain sequences. Maybe this cannot be done for every irrational number, but for important numbers like pi, e, sqrt(2), the golden ratio, and so on. One could use a similar construction to show the listener what infinity is:

intro infinity;
(> infinity (next naturals));
(> infinity (next naturals));
(> infinity (next naturals));
(> infinity (next naturals));
(> infinity (next naturals));

Maybe one has to use more than one generator to transport the concept.

Does this make any sense?