Live data from Hacker News

More intuitive partial function application in Python

github.com

31–36 of 36 posts

Re: More intuitive partial function application in Python

#31

I was gonna say cool for FP guys but alien to the Python world, but then i saw the f(..., x=1) syntax and decided you're a genius. Really nice idea. In practice i worry about static checkers and IDE param hints though, how have you fared with these? Not your fault at all, but mypy/pyright have very poor support for wrappers like this, and in IDEs it's common for their arg hints to devolve to a copout (args, kwargs) a…

> Not your fault at all, but mypy/pyright have very poor support for wrappers like this, and in IDEs it's common for their arg hints to devolve to a copout (args, kwargs) as well. You might be able to annotate it accurately with generics, ParamSpec and Concatenate[1]. [1] https://www.python.org/dev/peps/pep-0612/

I'll give this a look.

Re: More intuitive partial function application in Python

#32

Great to see this! Thanks for working on it. Could you compare it to functools.partial? In the example on the Readme: import better_partial as bp @bp.partial def some_operation(x, p1, p2): return (x + p1) * p2 It claims that the bp approach is superior because: func = some_operation(bp._, 10, 20) ...is better than: func = lambda x: some_operation(x, 10, 20) But is it better than just: partial(some_operation, p1=10, p…

Yes! I definitely need to beef up the README. I wrote up a gist for some other commenters below which I can incorporate as part of the justification.

https://gist.github.com/chrisgrimm/64bca66f14528cfda6d865cc2...

Re: More intuitive partial function application in Python

#33

Current solutions: >>> list(map(partial(pow, exp=3), range(10))) [0, 1, 8, 27, 64, 125, 216, 343, 512, 729] >>> list(map(lambda base: pow(base, 3), range(10))) [0, 1, 8, 27, 64, 125, 216, 343, 512, 729] >>> [pow(base, 3) for base in range(10)] [0, 1, 8, 27, 64, 125, 216, 343, 512, 729] Proposed solution: list(map(bp.partial(pow)(bp._, 3), range(10)) ISTM the only time you come out a little ahead is if you know in adv…

I'm glad you like the recipe :-)

What if you have a function "f" that takes like 10 arguments and you need to pass it to a function "g" that expects as input a function takes 8 arguments.

  @partial
  def f(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10):
     return "stuff"
  
  g(f(..., p4=1, p7=2))
  #  seems nicer than
  g(lambda p1, p2, p3, p5, p6, p8, p9, p10: f(p1, p2, p3, 1, p5, p6, 2, p8, p9, p10))

Re: More intuitive partial function application in Python

#34
post #9

whats wrong with functools.partial? I don't see that anywhere in the arguments.. all you say is "I find functools.partial unintuitive".. why? its a simple wrapper.

here's an example of one of the behaviors of functools.partial that I find unintuitive / undesirable: https://gist.github.com/chrisgrimm/64bca66f14528cfda6d865cc2...

No post body was provided.

Re: More intuitive partial function application in Python

#35

Current solutions: >>> list(map(partial(pow, exp=3), range(10))) [0, 1, 8, 27, 64, 125, 216, 343, 512, 729] >>> list(map(lambda base: pow(base, 3), range(10))) [0, 1, 8, 27, 64, 125, 216, 343, 512, 729] >>> [pow(base, 3) for base in range(10)] [0, 1, 8, 27, 64, 125, 216, 343, 512, 729] Proposed solution: list(map(bp.partial(pow)(bp._, 3), range(10)) ISTM the only time you come out a little ahead is if you know in adv…

Nit: List comprehension looks better for expressions (preferable over lambda+map)

Re: More intuitive partial function application in Python

#36

Current solutions: >>> list(map(partial(pow, exp=3), range(10))) [0, 1, 8, 27, 64, 125, 216, 343, 512, 729] >>> list(map(lambda base: pow(base, 3), range(10))) [0, 1, 8, 27, 64, 125, 216, 343, 512, 729] >>> [pow(base, 3) for base in range(10)] [0, 1, 8, 27, 64, 125, 216, 343, 512, 729] Proposed solution: list(map(bp.partial(pow)(bp._, 3), range(10)) ISTM the only time you come out a little ahead is if you know in adv…

I'm glad you like the recipe :-) What if you have a function "f" that takes like 10 arguments and you need to pass it to a function "g" that expects as input a function takes 8 arguments. @partial def f(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10): return "stuff" g(f(..., p4=1, p7=2)) # seems nicer than g(lambda p1, p2, p3, p5, p6, p8, p9, p10: f(p1, p2, p3, 1, p5, p6, 2, p8, p9, p10))

First mistake, making a function with 10 parameters.

We have data structures for that, if you need it. Just pass in a big struct/named tuple as one parameter. Bonus points if it is type hinted.

Post reply on HN