Rather than adding a magical “PLACEHOLDER” sentinel value, another
common solution is to define a version of partial that binds from the
right rather than the left.
Here’s an untested implementation:
def partial_right(func, /, *args, **keywords):
def newfunc(*fargs, **fkeywords):
newkeywords = {**keywords, **fkeywords}
return func(*fargs, *args, **newkeywords)
newfunc.func = func
newfunc.args = args
newfunc.keywords = keywords
return newfunc
It is a one line change from the code given in the docs:
https://docs.python.org/3/library/functools.html#functools.partial
I don’t think this is a very common need. As far as I can tell, none of
the major functional-programming languages that support partial
application provide the functionality. Although that might be because
their partial application are built on currying?
In any case, you are not the only one to request this sort of feature,
at least in the Javascript world:
opened 11:32PM - 24 Jun 13 UTC
closed 02:10PM - 06 Jul 13 UTC
breaking change
The current implementation of `partial` and `bind` allows arguments to be pre-su… pplied only from left to right. This misses the highly practical use case that it is the subject (the first argument) that we want to apply later. In fact, I would argue that supplying initial arguments later is more often the case than providing latter arguments later.
In my proposal for #1155 makes a good case for partial application where the subject is applied later. It would be useful if `partial` made it possible to curry designated arguments, vs. always having to pre-fill from left to right. Sugar.js offers a `fill` method that does exactly this. I propose the same feature be extended to underscore. To skip an argument for later application one would pass in a placeholder. Sugar.js uses `undefined` for this but we could use the underscore object itself (which makes a good placeholder).
```
_.map(comedians, _.partial(_.pick, _, 'name')) //explicit currying
_.map(comedians, _.pick('name')) //implicit currying
_.filter(comedians, _.partial(_.match, _, {type: 'stooge'})) //explicit
_.filter(comedians, _.match({type: 'stooge'})) //implicit
_.where(comedians, {type: 'stooge'}) //equivalent to the above
_.filter(comedians, _.partial(_.has, _, 'type'))
```
The implicit currying shown above is a carry over of the idea presented in #1155. The focus here is that this idea could be achieved without extending functions to curry themselves if `partial` is extended to allow for it.
Consider this code take from the underscore documentation.
```
var add = function(a, b) { return a + b; };
add5 = _.partial(add, 5);
add5(10);
```
This example doesn't make it obvious that we are currying into the leftmost position because a 5 being passed to either `a` or `b` yields the same effect. For that reason, I would recommend supplying another example. A better example would be
```
var divide = function(a, b) { return a / b; };
halve = _.partial(divide, _, 2);
halve(10); // => 5
twoDividedBy = _.partial(divide, 2)
twoDividedBy(.5) // => 4
```
because it illustrates that omitting the subject for later is a completely valid scenario. It also makes it clear (without reading any documentation) what got pre-filled and what got applied later.
3 Likes