admin管理员组文章数量:1410712
I would like to implement something similar to this OCaml in Python:
let example = fun v opt_n ->
let fltr = fun i -> i mod 2 = 0 in
let fltr = match opt_n with
| None -> fltr
| Some n -> fun i -> (i mod n = 0 && fltr n) in
fltr v
This is easily composable/extendable, I can add as many predicates as I want at runtime. This is of course a simplified example, in real life I have many optional inclusion/exclusion sets, and predicate checks for membership.
Doing this the naive way in Python fails:
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)
This is annoying because it seems that since fltr
can only appear once on the left side of the assignment, I have to inline the initial fltr
in every case afterward:
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)
Is there any way to fix my mess, maybe I am missing something, and/or what is the recommended way to compose predicates in Python?
I would like to implement something similar to this OCaml in Python:
let example = fun v opt_n ->
let fltr = fun i -> i mod 2 = 0 in
let fltr = match opt_n with
| None -> fltr
| Some n -> fun i -> (i mod n = 0 && fltr n) in
fltr v
This is easily composable/extendable, I can add as many predicates as I want at runtime. This is of course a simplified example, in real life I have many optional inclusion/exclusion sets, and predicate checks for membership.
Doing this the naive way in Python fails:
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)
This is annoying because it seems that since fltr
can only appear once on the left side of the assignment, I have to inline the initial fltr
in every case afterward:
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)
Is there any way to fix my mess, maybe I am missing something, and/or what is the recommended way to compose predicates in Python?
Share Improve this question edited Mar 20 at 0:19 Chris 36.9k6 gold badges33 silver badges55 bronze badges asked Mar 9 at 14:55 DenisDenis 1,5952 gold badges18 silver badges31 bronze badges 5 |1 Answer
Reset to default 3When you write
fltr = lambda i: fltr(i) and i % opt_n == 0
fltr
remains a free variable inside the lambda expression, and will be looked up when the function is called; it's not bound to the old definition of fltr
in place when you evaluate the lambda expression.
You need some way to do early binding; one option is to bind the current value of fltr
to a new variable that's local to the lambda expression, namely another parameter:
fltr = lambda i, cf=fltr: cf(i) and i % opt_n == 0
Not the cleanest solution. If you don't mind an additional function call, you can define an explicit composition function:
def pred_and(f, g):
return lambda x: f(x) and g(x)
then use that to compose the old fltr
with another predicate to produce a new filter.
def example(v: int, opt_n=None):
fltr = lambda i: i % 2 == 0
if opt_n is not None:
# fails miserably -> maximum recursion depth exceeded
fltr = pred_and(fltr, lambda i: i % opt_n == 0)
return fltr(v))
(I don't know OCaml very well, but pred_and
is somewhat like the use of an applicative functor in Haskell, e.g. pred_and = liftA2 (&&)
.)
本文标签: functional programmingPython39s predicate compositionStack Overflow
版权声明:本文标题:functional programming - Python's predicate composition - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1744868555a2629488.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
lambda
– furas Commented Mar 9 at 15:53example
function to do and how/where you intend to be able to add predicates? What doesopt_n
mean? – mkrieger1 Commented Mar 9 at 15:54