[Python-ideas] Syntactic sugar to declare partial functions

Steven D'Aprano steve at pearwood.info
Sat Aug 4 13:57:45 EDT 2018


On Sat, Aug 04, 2018 at 09:03:50AM -0700, Fabrizio Messina wrote:

> At the moment we have to load the *partial* function from the *functool* 
> library, and apply it to an existing function
[...]

> While partial expose the mechanism excellently its instantiation method is, 
> at times, not very friendly,

I disagree with *both* of those statements.

As an implementation of partial function application, partial() has a 
couple of weaknesses:

- no support for applying arguments from the right, except by keyword;

- no automatic or easy way to inherit docstrings from the original
  function;

- even if you manually set the partial function object's docstring,
  help() ignores it. (That's possibly not partial's fault.)


On the other hand, I think that

   partial(func, arg, kw=value)

is plenty friendly.



> I would like to propose a syntactic sugar to 
> create partial functions, in the case you create a partial function using *curly 
> braces*:
[...]

> add_2 = add{2}

Too obscure. What do curly braces have to do with partial function 
application? It seems pretty arbitrary.

I know that ultimately ALL conventions are arbitrary, but we already 
have a couple of very strong conventions for curly braces (dicts and 
sets) and mathematicians have a few strong conventions for partial 
function application and currying, neither of which uses curly brackets.

Besides, if we ever did support some sort of function-call-like syntax 
using braces spam{...} I would hope it would be for something more 
important than partial function application.


You should consider prior art:

- Scala uses a special value, which when passed to a function, 
  returns a new function:

  # using Python syntax
  def add(a, b): return a+b

  add1 = add(1, _)  # like partial(add, 1)


- Perl6 gives all functions an "assuming" method:

  add1 = add.assuming(1)


- ML and Haskell define all functions as single-argument functions.
  Multiple arguments are actually just syntactic sugar:

      func(a, b, c)  # syntactic sugar for func(a)(b)(c)

  so partial application from the left is trivial:

  add1 = add(1)


- but most other languages that I know of use a function or keyword 
  "partial" (or sometimes, and inaccurately, "curry").



> Now all this can already be done with partial,

Indeed it can.


> but adding this syntactic 
> sugar would reduce the perception of `partial` as an advanced feature, 
> alleviating the use of closures created only for the sake of avoiding an 
> explicit partial.

I don't think that is the case. I think that partial, and currying, are 
both relatively advanced features. Many programmers never quite grasp, 
or become comfortable with, functions as values.


If we were to push partial application as a mainstream technique, and 
I'm not saying we should, but if we did, my vote would be to give 
function (and method) objects a partial method:

    add1 = add.partial(1)

although possibly a less jargon name would be nicer:

    add1 = add.given(1)



-- 
Steve


More information about the Python-ideas mailing list