In Python, collections are generally generated in comprehensions (I think).
But when it gets a little complicated, the comprehensions are hard to read.
#Forcibly include the Fizz Buzz list
fb = ["Fizz Buzz" if i % 15 == 0
else "Fizz" if i % 3 == 0
else "Buzz" if i % 5 == 0
else i
for i in range(30)]
In this case, it is easier to see if you write a for statement.
However, the writing style of making small changes while exposing the object before initialization is somewhat guilty (if the functional preference is strong).
fb = []
for i in range(30):
if i % 15 == 0:
fb.append("Fizz Buzz")
elif i % 3 == 0:
fb.append("Fizz")
elif i % 5 == 0:
fb.append("Buzz")
else:
fb.append(i)
what to do?
It is possible to define a generator with yield and create a collection based on it.
def _fb():
for i in range(30):
if i % 15 == 0:
yield "Fizz Buzz"
elif i % 3 == 0:
yield "Fizz"
elif i % 5 == 0:
yield "Buzz"
else:
yield i
fb = list(_fb)
↑ is not bad, but after defining the generator, the procedure of assigning it to a variable through the list function is complicated.
Also, if you forget to list it and receive the iterator directly as a variable, it can be a hotbed of bugs.
I want the definition using yield to be interpreted as the definition of the list as it is.
This can be achieved with a decorator.
def comprehension(collector):
def ret(func):
return collector(func())
return ret
#When you execute the following, the list is assigned to the variable "fb".
@comprehension(list)
def fb():
for i in range(30):
if i % 15 == 0:
yield "Fizz Buzz"
elif i % 3 == 0:
yield "Fizz"
elif i % 5 == 0:
yield "Buzz"
else:
yield i
The first source material is the decorator called collecting in the library funcy. Turn the generator function into a function that returns a list. With it, Fizz Buzz can be written as:
from funcy import collecting
@collecting
def _fb():
for i in range(30):
if i % 15 == 0:
yield "Fizz Buzz"
elif i % 3 == 0:
yield "Fizz"
elif i % 5 == 0:
yield "Buzz"
else:
yield i
fb = _fb()
However, it is troublesome to define the function once.
Racket's [for / list](https://docs.racket-lang.org/reference/for.html#%28form._%28%28lib._racket%2Fprivate%2Fbase..rkt%29._for%2Flist% I thought if I could write something like 29% 29), I came up with a solution that does not return a function with a decorator.
Recommended Posts