<div dir="ltr"><div><div><div><div>'is_email_address' is a special tuple which contains functions. (is_email_address[0] returns is_string)<br>For help, it's a feature I've not implemented but it's easy to return the help of each function, plus details as each function has an object representing it's signature.<br></div><br>For traceback mangling, I don't see what is the problem.<br></div>When you call is_email_address(something) it pretty like if you've called:<br></div>def is_email_address(value):<br> is_string(value)<br> has_char('@', value)<br> has_user(value)<br> has_domain(value)<br></div> return value<br><div><div><div><div><br></div></div></div></div></div><div class="gmail_extra"><br><div class="gmail_quote">2015-05-11 19:08 GMT+02:00 Douglas La Rocca <span dir="ltr"><<a href="mailto:larocca@abiresearch.com" target="_blank">larocca@abiresearch.com</a>></span>:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div dir="ltr">
<div style="font-size:12pt;color:#000000;background-color:#ffffff;font-family:Calibri,Arial,Helvetica,sans-serif">
<p>Operator overloading (>>) has <span style="font-family:Calibri,Arial,Helvetica,sans-serif;font-size:16px;background-color:rgb(255,255,255)">
intuitive </span>readability but in my experience it's better have functions remain "ordinary" functions, not class instances so you know what to expect regarding the type and so on. <span style="font-size:12pt">The other downside is that with (>>) only the
functions you wrap can play together.</span></p>
<p><br>
<span style="font-family:Calibri,Arial,Helvetica,sans-serif;font-size:16px;background-color:rgb(255,255,255)">Leaving aside the readability concern, </span>the really major problem is that your tracebacks are so badly mangled. And if your implementation
of the composition function uses recursion it gets even worse.<br>
</p>
<p><br>
</p>
<p>You also lose the benefits of reflection/inspection--for example, with the code below, what happens if I call help ?? in ipython on `<span style="color:rgb(40,40,40);font-family:Calibri,Arial,Helvetica,sans-serif;font-size:16px;background-color:rgb(255,255,255)">is_email_address</span>`?<br>
</p>
<p><br>
</p>
<div style="color:rgb(40,40,40)">
<hr style="display:inline-block;width:98%">
<div dir="ltr"><font style="font-size:11pt" face="Calibri, sans-serif" color="#000000"><b>From:</b> Python-ideas <python-ideas-bounces+larocca=<a href="mailto:abiresearch.com@python.org" target="_blank">abiresearch.com@python.org</a>> on behalf of Gregory Salvan <<a href="mailto:apieum@gmail.com" target="_blank">apieum@gmail.com</a>><br>
<b>Sent:</b> Monday, May 11, 2015 12:13 PM<br>
<b>To:</b> Guido van Rossum<br>
<b>Cc:</b> <a href="mailto:python-ideas@python.org" target="_blank">python-ideas@python.org</a><span class=""><br>
<b>Subject:</b> Re: [Python-ideas] Partial operator (and 'third-party methods' and 'piping') [was Re: Function composition (was no subject)]</span></font>
<div> </div>
</div><div><div class="h5">
<div>
<div dir="ltr">
<div>
<div>
<div>
<div>I don't want to insist and I respect your point of view, I just want to give a simplified real life example to show that function composition can be less painful than another syntax.<br>
<br>
</div>
When validating a lot of data you may want to reuse parts of already writen validators. It can also be a mess to test complex data validation.<br>
</div>
You can reduce this mess and reuse parts of your code by writing atomic validators and compose them.<br>
<br>
</div>
<div># sorry for using my own lib, but if I make no mistakes this code functions, so...<br>
</div>
<div><br>
import re<br>
</div>
<div>from lawvere import curry # curry is an arrow without type checking, inherits composition, mutiple dispatch<br>
</div>
<div><br>
user_match = re.compile("^[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*$").match<br>
domain_match = re.compile("^(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$").match<br>
strict_user_match = re.compile("^[a-z0-9][a-z0-9_-]+(?:\.[a-z0-9_-]+)*$").match<br>
<br>
</div>
<div>@curry<br>
</div>
<div>def is_string(value):<br>
assert isinstance(value, str), '%s is not a string' %value<br>
</div>
return value<br>
<br>
</div>
@curry
<div>
<div>def apply_until_char(func, char, value):<br>
</div>
<div> func(value[:value.index(char)])<br>
<div> return value<br>
</div>
<br>
</div>
<div>@curry</div>
<div>
<div>def apply_from_char(func, char, value):<br>
</div>
<div> func(value[value.index(char) + 1:])<br>
</div>
<div> return value<br>
</div>
</div>
<br>
@curry<br>
<div>
<div>def has_char(char, value):<br>
assert value.count(char) == 1<br>
</div>
<div> return value<br>
<br>
@curry<br>
</div>
<div>def assert_ends_with(text, value):<br>
</div>
<div> assert value.endswith(text), '%s do not ends with %s' % (value, text)<br>
</div>
<div> return value</div>
<div><br>
@curry<br>
def assert_user(user):<br>
assert user_match(user) is not None, '%s is not a valid user name' % value<br>
</div>
<div> return user<br>
</div>
<div><br>
@curry<br>
def assert_strict_user(user):<br>
assert strict_user_match(user) is not None, '%s is not a valid strict user' % value<br>
</div>
<div> return user<br>
</div>
<div><br>
@curry<br>
def assert_domain(domain):<br>
assert domain_match(domain) is not None, '%s is not a valid domain name' % value<br>
</div>
<div> return domain<br>
<br>
</div>
<div># currying (be made with partial)<br>
</div>
<div>has_user = apply_until_char(assert_user, '@')<br>
</div>
<div>has_strict_user = apply_until_char(assert_strict_user, '@')<br>
</div>
<div>has_domain = apply_from_char(assert_domain, '@')<br>
<br>
</div>
<div># composition:<br>
</div>
<div>is_email_address = is_string >> has_char('@') >> has_user >> has_domain<br>
<div>is_strict_email_address = is_string >> has_char('@') >> has_strict_user >> has_domain<br>
<br>
</div>
<div># we just want org adresses ?<br>
</div>
<div>is_org_addess = is_email_address >> assert_ends_with('.org')<br>
</div>
<div><br>
<br>
</div>
<div>I found a lot of interest in this syntax, mainly for testing purpose, readability and maintenability of code.<br>
</div>
<div>No matters if I'm a fish out of python waters. :)<br>
</div>
<div><br>
</div>
<br>
</div>
<div>
<div>
<div><br>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="gmail_extra"><br>
<div class="gmail_quote">2015-05-11 16:41 GMT+02:00 Guido van Rossum <span dir="ltr">
<<a href="mailto:guido@python.org" target="_blank">guido@python.org</a>></span>:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div dir="ltr">
<div>As long as I'm "in charge" the chances of this (or anything like it) being accepted into Python are zero. I get a headache when I try to understand code that uses function composition, and I end up having to laboriously rewrite it using more traditional
call notation before I move on to understanding what it actually does. Python is not Haskell, and perhaps more importantly, Python users are not like Haskel users. Either way, what may work out beautifully in Haskell will be like a fish out of water in Python.<br>
<br>
</div>
I understand that it's fun to try to sole this puzzle, but evolving Python is more than solving puzzles. Enjoy debating the puzzle, but in the end Python will survive without the solution.<span><font color="#888888"><br>
<div><br>
<div>
<div class="gmail_extra">-- <br>
<div>--Guido van Rossum (<a href="http://python.org/~guido" target="_blank">python.org/~guido</a>)</div>
</div>
</div>
</div>
</font></span></div>
<br>
_______________________________________________<br>
Python-ideas mailing list<br>
<a href="mailto:Python-ideas@python.org" target="_blank">Python-ideas@python.org</a><br>
<a href="https://mail.python.org/mailman/listinfo/python-ideas" target="_blank">https://mail.python.org/mailman/listinfo/python-ideas</a><br>
Code of Conduct: <a href="http://python.org/psf/codeofconduct/" target="_blank">http://python.org/psf/codeofconduct/</a><br>
</blockquote>
</div>
<br>
</div>
</div>
</div></div></div>
</div>
</div>
</blockquote></div><br></div>