moved lispy from 02 to 18

This commit is contained in:
Luciano Ramalho
2021-09-15 22:48:08 -03:00
parent 00e4741926
commit 6527037ae7
38 changed files with 590 additions and 1219 deletions

View File

@@ -5,7 +5,7 @@ import itertools
def aritprog_gen(begin, step, end=None):
first = type(begin + step)(begin)
ap_gen = itertools.count(first, step)
if end is not None:
ap_gen = itertools.takewhile(lambda n: n < end, ap_gen)
return ap_gen
if end is None:
return ap_gen
return itertools.takewhile(lambda n: n < end, ap_gen)
# end::ARITPROG_ITERTOOLS[]

View File

@@ -0,0 +1,43 @@
"""
A coroutine to compute a running average
# tag::CORO_AVERAGER_TEST[]
>>> coro_avg = averager() # <1>
>>> next(coro_avg) # <2>
0.0
>>> coro_avg.send(10) # <3>
10.0
>>> coro_avg.send(30)
20.0
>>> coro_avg.send(5)
15.0
# end::CORO_AVERAGER_TEST[]
# tag::CORO_AVERAGER_TEST_CONT[]
>>> coro_avg.send(20) # <1>
16.25
>>> coro_avg.close() # <2>
>>> coro_avg.close() # <3>
>>> coro_avg.send(5) # <4>
Traceback (most recent call last):
...
StopIteration
# end::CORO_AVERAGER_TEST_CONT[]
"""
# tag::CORO_AVERAGER[]
from collections.abc import Generator
def averager() -> Generator[float, float, None]: # <1>
total = 0.0
count = 0
average = 0.0
while True: # <2>
term = yield average # <3>
total += term
count += 1
average = total/count
# end::CORO_AVERAGER[]

View File

@@ -0,0 +1,96 @@
"""
A coroutine to compute a running average.
Testing ``averager2`` by itself::
# tag::RETURNING_AVERAGER_DEMO_1[]
>>> coro_avg = averager2()
>>> next(coro_avg)
>>> coro_avg.send(10) # <1>
>>> coro_avg.send(30)
>>> coro_avg.send(6.5)
>>> coro_avg.close() # <2>
# end::RETURNING_AVERAGER_DEMO_1[]
Catching `StopIteration` to extract the value returned by
the coroutine::
# tag::RETURNING_AVERAGER_DEMO_2[]
>>> coro_avg = averager2()
>>> next(coro_avg)
>>> coro_avg.send(10)
>>> coro_avg.send(30)
>>> coro_avg.send(6.5)
>>> try:
... coro_avg.send(STOP) # <1>
... except StopIteration as exc:
... result = exc.value # <2>
...
>>> result # <3>
Result(count=3, average=15.5)
# end::RETURNING_AVERAGER_DEMO_2[]
Using `yield from`:
# tag::RETURNING_AVERAGER_DEMO_3[]
>>> def compute():
... res = yield from averager2(True) # <1>
... print('computed:', res) # <2>
... return res # <3>
...
>>> comp = compute() # <4>
>>> for v in [None, 10, 20, 30, STOP]: # <5>
... try:
... comp.send(v) # <6>
... except StopIteration as exc: # <7>
... result = exc.value
received: 10
received: 20
received: 30
received: <Sentinel>
computed: Result(count=3, average=20.0)
>>> result # <8>
Result(count=3, average=20.0)
# end::RETURNING_AVERAGER_DEMO_3[]
"""
# tag::RETURNING_AVERAGER_TOP[]
from collections.abc import Generator
from typing import Union, NamedTuple
class Result(NamedTuple): # <1>
count: int # type: ignore # <2>
average: float
class Sentinel: # <3>
def __repr__(self):
return f'<Sentinel>'
STOP = Sentinel() # <4>
SendType = Union[float, Sentinel] # <5>
# end::RETURNING_AVERAGER_TOP[]
# tag::RETURNING_AVERAGER[]
def averager2(verbose: bool = False) -> Generator[None, SendType, Result]: # <1>
total = 0.0
count = 0
average = 0.0
while True:
term = yield # <2>
if verbose:
print('received:', term)
if isinstance(term, Sentinel): # <3>
break
total += term # <4>
count += 1
average = total / count
return Result(count, average) # <5>
# end::RETURNING_AVERAGER[]

View File

@@ -0,0 +1,7 @@
from collections.abc import Iterator
def fibonacci() -> Iterator[int]:
a, b = 0, 1
while True:
yield a
a, b = b, a + b

View File

@@ -21,7 +21,7 @@ class Sentence:
def __iter__(self):
for word in self.words: # <1>
yield word # <2>
return # <3>
# <3>
# done! <4>