The common python pattern
def foo():
tmp = []
for x in y:
...
tmp.append(z)
return tmpcan be simplified to
@cast
def foo() -> list:
for x in y:
...
yield zusing the decorator cast, which I have implemented here.
Some examples:
@cast
def nums() -> dict:
yield 1, 'one'
yield 2, 'two'
# {1: 'one', 2: 'two'}
@cast
def hello() -> (str.upper, ', '.join):
yield "Hello"
yield "world"
# 'HELLO, WORLD'A decorator for function composition as follows would be useful.
compose = lambda f: lambda g: lambda *a, **k: f(g(*a, **k))
@compose(str.upper)
@compose(', '.join)
def hello():
yield "Hello"
yield "world"However, the notation achieved by cast is superiour.
We can nicely loop through generators using for loops. However, for
coroutines, this is not possible, since we have no way of sending values. I
therefore suggest allowing continue to take an optional expression to send to the generator. For example, in
for x in g:
...
continue ythe first value of x would be obtained from next(g) as usual, but
subsequent values are obtained from g.send(y) (of course, allowing continue
to be used in branches as it is currently, with g.send(None) or next(g)
used if an iteration ends without a continue).
Currently this has to be done using the more clumsy
x = next(g)
try:
while True:
...
x = g.send(y)
except StopIteration:
passIterators raise StopIteration exceptions to stop. In particular, generators
raise the exception when they return, with the value property set to the
returned value. I suggest using the finally keyword for accessing this as follows:
def gen():
yield 'foo'
return 'bar'
for x in gen():
print(x)
finally y:
print(y) # prints 'bar'Supplying a variable to finally would be optional.
This would also be useful with the else case for for loops: the else case
happens if the loop ends without breaking, and the finally case occurs
regardless. Placing the finally case before the else case would simplify
some code.
If the loop is terminated by break, the value should be None. Moreover,
break could be extended to also take an expression to give to finally.
for x in range(1):
break 'bar'
finally y:
print(y) # prints 'bar'else EXPRESSION:
...as shorthand for
else:
assert(EXPRESSION)
...though perhaps a new exception type should be used.