from itertools import permutations
def n_queens(n):
for p in permutations(range(n)):
if len({c + i for i, c in enumerate(p)}) == len({c - i for i, c in enumerate(p)}) == n:
yield p from itertools import permutations
def n_queens(n):
for p in permutations(range(n)):
if len({c + i for i, c in enumerate(p)}) == len({c - i for i, c in enumerate(p)}) == n:
yield p def n_queens(n):
yield from (p for p in permutations(range(n))
if len({c + i for i, c in enumerate(p)}) ==
len({c - i for i, c in enumerate(p)}) == n)
It also illustrates how much neater list comprehensions can be in Python versus map/filter since its lambda functions are fairly verbose (even though there's a straightforward correspondence between them): def n_queens(n):
return filter(lambda p:
len(set(map(lambda x: x[1] + x[0], enumerate(p)))) ==
len(set(map(lambda x: x[1] - x[0], enumerate(p)))) == n,
permutations(range(n)))Python's iterators are mutation-based, so not really functional. `yield` is based around pause-resume of function execution, so not really functional. `permutations` is just a function that wraps a list (or iterator coercible to one (which mutates the iterator)) and returns a (mutable) iterator.
A `for` comprehension desugars to a `for` loop with `yield` if it's a lazy comprehension, `append` if it's a list comprehension or `add` if it's a set comprehension, which of course involves mutation.
Basically nothing here is mutation free. That, at least IMO, means it's not functional.
It's great that functional languages were first to catch onto these ideas, but that doesn't mean that anything else that uses them becomes functional. The interface isn't even functional, since in code like
foo = iter((1, 2, 3))
{x for x in foo}
`foo` is mutated. No "true" functional language would accept that ;).Sure, but Python wasn't the first imperative programming language. (An aside: that's not strictly true anyway; the error thrown when you do 1 + [] is a side effect.)