[Python-ideas] @partials = decorators
Ron Adam
ron3200 at gmail.com
Sun Feb 16 08:22:25 CET 2014
On 02/10/2014 01:44 PM, Alex Rodrigues wrote:
> This is pretty cumbersome to write out every time so I wanted a function that could just be called on arbitrary histograms like side_by_side(data1.hist(bottom=0.1, log=True), data2.hist(bins=10)). The problem is that I do not have the axes available when I call the function and once I pass the plots to the function they have already been evaluated and there is no way to add arguments retroactively. With the continuation syntax it would be amazingly easier:
>
> def side_by_side(plot1, plot2):
> fig = plt.figure()
> ax1 = plt.subplot(121)
> ax2 = plt.subplot(122)
> plot1(ax=ax1)
> plot2(ax=ax2)
>
> side_by_side(@data.hist(), @data.hist(log=True)) #Technically the first
> one doesn't need to be a continuation, but whatever.
>
> tldr; I like it and see a decent number of applications. Also I'm
> wondering if you'd have to chain continuations
> @@a('arg1')('arg2')('arg3').
These functions are more like partials, rather than continuations, which
pause in the middle of the function.
No, you wouldn't need to chain them since each incomplete call returns a
incomplete callable object.
So this works...
_()(f)(a1)(a2)(a3) --> result
The latest version I have, ... it's evolving as I go... has two parts.
1. A caller function. Which attempts to call the function.
2. A callable holder object. Which holds the incomplete call state.
Both of these take any number of arguments. The only requirement is that
the first item in the sequence of arguments be a callable.
You can be initiate the arguments with either the caller, or the holder,
depending on weather or not you want to delay the initial call attempt.
The caller will try to call the function with the initially given arguments
and if that fails, it instead returns a callable holder object. When the
holder is called, it will collect more arguments and pass those to the
caller. Which may return a final result or another holder.
If you apply a non callable object to these, it just gets returned. That
allows you to catch deferred results, and pass other things through. A
sort of explicit lazy evaluation.
So far, I've found these are pretty good at doing lambda calculus,
flattening decorators, and can be useful in deferring a call in some
situations where normally you would use a lambda function or a nested
function definition. And they may also be good at collecting non
localised, or disjointed data.
It's also nice that they are higher order functions that accept most any
callable.
The main issue is there is not a reliable way to get the argument count of
builtin callable function or class. Python functions have an arg_count
attribute in the code object. But builtin functions lack that attribute.
(hint, hint...)
So for now, these are more conceptual than useful, as they will break under
certain situations... like giving too many arguments, or if a TypeError
exception comes from within the function instead of during the call process.
Cheers,
Ron
More information about the Python-ideas
mailing list