Gostaria de implementar algo semelhante a este OCaml em Python:
let example = fun v opt_n ->
let fltr = fun i -> i mod 2 = 0
let fltr = match opt_n with
| None -> fltr
| Some n -> fun i -> i mod n = 0 && fltr(n)
fltr v
Isso é facilmente componível/extensível, posso adicionar quantos predicados eu quiser em tempo de execução. Este é, claro, um exemplo simplificado, na vida real tenho muitos conjuntos opcionais de inclusão/exclusão e verificações de predicados para associação.
Fazer isso de forma ingênua em Python falha:
def example(v: int, opt_n=None):
"""
doesn't work!
"""
# doesn't need to be a lambda, an explicitely defined function fails too
fltr = lambda i: i % 2 == 0
if opt_n is not None:
# fails miserably -> maximum recursion depth exceeded
fltr = lambda i: fltr(i) and i % opt_n == 0
return fltr(v)
example(10, 5)
Isso é irritante porque parece que, como fltr
só pode aparecer uma vez no lado esquerdo da tarefa, tenho que colocar a inicial fltr
em todos os casos seguintes:
def example(v: int, opt_n=None, opt_m=None):
"""annoying but works"""
fltr = None
# some inital filters
pred_0 = lambda _: True # do some real checks ...
pred_1 = lambda _: True # do some real checks ...
if opt_n is not None:
# fltr is inlined, only appears on left side, now it works
fltr = lambda i: pred_0(i) and pred_1(i) and opt_n % 2 == 0
if opt_m is not None:
# much repetition
fltr = lambda i: pred_0(i) and pred_1(i) and opt_n % 3 == 0
if fltr is None:
# inlined again
fltr = lambda i: pred_0(i) and pred_1(i)
return fltr(v)
Existe alguma maneira de consertar minha bagunça, talvez eu esteja esquecendo de alguma coisa, e/ou qual é a maneira recomendada de compor predicados em Python?