<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w="urn:schemas-microsoft-com:office:word" xmlns:m="http://schemas.microsoft.com/office/2004/12/omml" xmlns="http://www.w3.org/TR/REC-html40">

<head>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=us-ascii">
<meta name=Generator content="Microsoft Word 12 (filtered medium)">
<style>
<!--
 /* Font Definitions */
 @font-face
        {font-family:"Cambria Math";
        panose-1:2 4 5 3 5 4 6 3 2 4;}
@font-face
        {font-family:Calibri;
        panose-1:2 15 5 2 2 2 4 3 2 4;}
 /* Style Definitions */
 p.MsoNormal, li.MsoNormal, div.MsoNormal
        {margin:0in;
        margin-bottom:.0001pt;
        font-size:11.0pt;
        font-family:"Calibri","sans-serif";}
a:link, span.MsoHyperlink
        {mso-style-priority:99;
        color:blue;
        text-decoration:underline;}
a:visited, span.MsoHyperlinkFollowed
        {mso-style-priority:99;
        color:purple;
        text-decoration:underline;}
span.EmailStyle17
        {mso-style-type:personal-compose;
        font-family:"Calibri","sans-serif";
        color:windowtext;}
.MsoChpDefault
        {mso-style-type:export-only;}
@page Section1
        {size:8.5in 11.0in;
        margin:1.0in 1.0in 1.0in 1.0in;}
div.Section1
        {page:Section1;}
-->
</style>
<!--[if gte mso 9]><xml>
 <o:shapedefaults v:ext="edit" spidmax="1026" />
</xml><![endif]--><!--[if gte mso 9]><xml>
 <o:shapelayout v:ext="edit">
  <o:idmap v:ext="edit" data="1" />
 </o:shapelayout></xml><![endif]-->
</head>

<body lang=EN-US link=blue vlink=purple>

<div class=Section1>

<p class=MsoNormal>I&#8217;d like to express additional interest in python
patch 1660179, discussed here:<o:p></o:p></p>

<p class=MsoNormal><o:p>&nbsp;</o:p></p>

<p class=MsoNormal><a
href="http://mail.python.org/pipermail/patches/2007-February/021687.html">http://mail.python.org/pipermail/patches/2007-February/021687.html</a><o:p></o:p></p>

<p class=MsoNormal><o:p>&nbsp;</o:p></p>

<p class=MsoNormal>On several occasions, I&#8217;ve had the desire for
something like this.&nbsp; I&#8217;ve made due with lambda functions, but as was
mentioned, the lambda is clumsy and harder to read than functools.compose would
be.<o:p></o:p></p>

<p class=MsoNormal><o:p>&nbsp;</o:p></p>

<p class=MsoNormal>A potentially common use-case is when a library has a
multi-decorator use case in which they want to compose a meta decorator out of
one or more individual decorators.<o:p></o:p></p>

<p class=MsoNormal><o:p>&nbsp;</o:p></p>

<p class=MsoNormal>Consider the hypothetical library.<o:p></o:p></p>

<p class=MsoNormal><o:p>&nbsp;</o:p></p>

<p class=MsoNormal># we have three decorators we use commonly<o:p></o:p></p>

<p class=MsoNormal>def dec_register_function_for_x(func):<o:p></o:p></p>

<p class=MsoNormal>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # do something with func<o:p></o:p></p>

<p class=MsoNormal>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return func<o:p></o:p></p>

<p class=MsoNormal><o:p>&nbsp;</o:p></p>

<p class=MsoNormal>def dec_alter_docstring(func):<o:p></o:p></p>

<p class=MsoNormal>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # do something to func.__doc__<o:p></o:p></p>

<p class=MsoNormal>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return func<o:p></o:p></p>

<p class=MsoNormal><o:p>&nbsp;</o:p></p>

<p class=MsoNormal>def inject_some_data(data):<o:p></o:p></p>

<p class=MsoNormal>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; def dec_inject_data(func):<o:p></o:p></p>

<p class=MsoNormal>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; func.data = data # this may
not be legal, but assume it does something useful<o:p></o:p></p>

<p class=MsoNormal>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return func<o:p></o:p></p>

<p class=MsoNormal>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return dec_inject_data<o:p></o:p></p>

<p class=MsoNormal><o:p>&nbsp;</o:p></p>

<p class=MsoNormal># we could use these decorators explicitly throughout our
project<o:p></o:p></p>

<p class=MsoNormal>@dec_register_function_for_x<o:p></o:p></p>

<p class=MsoNormal>@dec_alter_docstring<o:p></o:p></p>

<p class=MsoNormal>@dec_inject_some_data(&#8216;foo data 1&#8217;)<o:p></o:p></p>

<p class=MsoNormal>def our_func_1(params):<o:p></o:p></p>

<p class=MsoNormal>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pass<o:p></o:p></p>

<p class=MsoNormal><o:p>&nbsp;</o:p></p>

<p class=MsoNormal>@dec_register_function_for_x<o:p></o:p></p>

<p class=MsoNormal>@dec_alter_docstring<o:p></o:p></p>

<p class=MsoNormal>@dec_inject_some_data(&#8216;foo data 2&#8217;)<o:p></o:p></p>

<p class=MsoNormal>def our_func_2(params):<o:p></o:p></p>

<p class=MsoNormal>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pass<o:p></o:p></p>

<p class=MsoNormal><o:p>&nbsp;</o:p></p>

<p class=MsoNormal>For two functions, that&#8217;s not too onerous, but if it&#8217;s
used throughout the application, it would be nice to abstract the collection of
decorators.&nbsp; One could do this with lambdas.<o:p></o:p></p>

<p class=MsoNormal><o:p>&nbsp;</o:p></p>

<p class=MsoNormal>def meta_decorator(data):<o:p></o:p></p>

<p class=MsoNormal>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return lambda func: dec_register_function_for_x(dec_alter_docstring(dec_inject_some_data(data)(func)))<o:p></o:p></p>

<p class=MsoNormal><o:p>&nbsp;</o:p></p>

<p class=MsoNormal>But to me, a compose function is much easier to read and much
more consistent with the decorator usage syntax itself.<o:p></o:p></p>

<p class=MsoNormal><o:p>&nbsp;</o:p></p>

<p class=MsoNormal>def meta_decorator(data):<o:p></o:p></p>

<p class=MsoNormal style='text-indent:.5in'>return compose(dec_register_function_for_x,
dec_alter_docstring, dec_inject_some_data(data))<o:p></o:p></p>

<p class=MsoNormal><o:p>&nbsp;</o:p></p>

<p class=MsoNormal>The latter implementation seems much more readable and
elegant.&nbsp; One doesn&#8217;t even need to know the decorator signature to
effectively compose meta_decorators.<o:p></o:p></p>

<p class=MsoNormal><o:p>&nbsp;</o:p></p>

<p class=MsoNormal>I&#8217;ve heard it said that Python is not a functional
language, but if that were really the case, then functools would not exist. In
addition to the example described above, I&#8217;ve had multiple occasions where
having a general purpose function composition function would have simplified the
implementation by providing a basic functional construct. While Python isn&#8217;t
primarily a functional language, it does have some functional constructs, and
this is one of the features that makes Python so versatile; one can program
functionally, procedurally, or in an object-oriented way, all within the same
language.<o:p></o:p></p>

<p class=MsoNormal><o:p>&nbsp;</o:p></p>

<p class=MsoNormal>I admit, I may be a bit biased; my first formal programming
course was taught in Scheme.<o:p></o:p></p>

<p class=MsoNormal><o:p>&nbsp;</o:p></p>

<p class=MsoNormal>Nevertheless, I believe functools is the ideal location for
a very basic and general capability such as composition.<o:p></o:p></p>

<p class=MsoNormal><o:p>&nbsp;</o:p></p>

<p class=MsoNormal>I realize this patch was rejected, but I&#8217;d like to
propose reviving the patch and incorporating it into functools.<o:p></o:p></p>

<p class=MsoNormal><o:p>&nbsp;</o:p></p>

<p class=MsoNormal>Regards,<o:p></o:p></p>

<p class=MsoNormal>Jason<o:p></o:p></p>

</div>

</body>

</html>