<div dir="ltr">Andrew, I agree with 100% of what you said; you put it much more clearly than I could.<div><br></div><div style>#soapbox</div><div>My point in stirring up all this is that we should not confuse "empirically bad" with "unpythonic". It is fine to reject something just because it's unpythonic, and does not fit into the rest of python's ecosystem, and it's fine to reject something because it is empirically bad.</div>

<div><br></div><div style>However, it is a mistake to say something (e.g. method chaining) is empirically bad *because* it is unpythonic. I say this because I think it does happen, whether intentionally or subconsciously. It's easy to blindly chant mantras like "explicit is better than implicit", but that blinds us to the deep and insightful trade-offs in these decisions, one of which is, of course, consistency with the rest of the ecosystem ("pythonicity").</div>

<div style>#end soapbox</div><div style><br></div><div style>Sorry for hijacking your thread! I think a better implementation for anonymous blocks (however it turns out) would be a wonderful thing; I've also abused decorators to do a lot of these things</div>

<div style><pre style="margin-top:0px;margin-bottom:0px;padding:0px;border:0px;font-size:12px;font-family:Consolas,'Liberation Mono',Courier,monospace;color:rgb(51,51,51);line-height:18px"><div class="" id="LC238" style="margin:0px;padding:0px 0px 0px 10px;border:0px">

<span class="" style="margin:0px;padding:0px;border:0px"><br></span></div><div class="" id="LC238" style="margin:0px;padding:0px 0px 0px 10px;border:0px"><span class="" style="margin:0px;padding:0px;border:0px">@sys.meta_path.append</span></div>

<div class="" id="LC239" style="margin:0px;padding:0px 0px 0px 10px;border:0px"><span class="" style="margin:0px;padding:0px;border:0px">@singleton</span></div><div class="" id="LC240" style="margin:0px;padding:0px 0px 0px 10px;border:0px">

<span class="" style="margin:0px;padding:0px;border:0px;font-weight:bold">class</span> <span class="" style="margin:0px;padding:0px;border:0px;color:rgb(68,85,136);font-weight:bold">ImportFinder</span><span class="" style="margin:0px;padding:0px;border:0px">(</span><span class="" style="margin:0px;padding:0px;border:0px;color:rgb(0,134,179)">object</span><span class="" style="margin:0px;padding:0px;border:0px">):</span></div>

<div class="" id="LC240" style="margin:0px;padding:0px 0px 0px 10px;border:0px"><span class="" style="margin:0px;padding:0px;border:0px">    ...</span></div></pre></div><div style><br></div><div style>I also think being able to pass multiple anonymous blocks into a function could also greatly reduce unnecessary uses of inheritance; I'm sure everyone has encountered situations where you are inheriting from a class, not because you actually *want* to create objects, but simply because you want to override one or more of the methods that the class has, such that when you call <span class="" style="margin:0px;padding:0px;border:0px;color:rgb(51,51,51);font-family:Consolas,'Liberation Mono',Courier,monospace;font-size:12px;line-height:18px;white-space:pre;background-color:rgb(255,255,255)">imp</span><span class="" style="margin:0px;padding:0px;border:0px;font-weight:bold;color:rgb(51,51,51);font-family:Consolas,'Liberation Mono',Courier,monospace;font-size:12px;line-height:18px;white-space:pre">.</span><span class="" style="margin:0px;padding:0px;border:0px;color:rgb(51,51,51);font-family:Consolas,'Liberation Mono',Courier,monospace;font-size:12px;line-height:18px;white-space:pre;background-color:rgb(255,255,255)">do_stuff(), </span>it will use the overriding methods. </div>

<div style><br></div><div style>In this way, inheritance is often used as an poor substitute for passing in multiple blocks into some function; it's a poor substitute because it is far more powerful than necessary, adding tons syntactic boilerplate and greatly increasing the number of things that can go wrong, when all you want is a pure function into which you can pass more than one block to customize it's behavior.</div>

</div><div class="gmail_extra"><br><br><div class="gmail_quote">On Tue, May 14, 2013 at 12:57 PM, Andrew Barnert <span dir="ltr"><<a href="mailto:abarnert@yahoo.com" target="_blank">abarnert@yahoo.com</a>></span> wrote:<br>

<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div class="HOEnZb"><div class="h5">On May 14, 2013, at 8:22, Terry Jan Reedy <<a href="mailto:tjreedy@udel.edu">tjreedy@udel.edu</a>> wrote:<br>


<br>
> On 5/14/2013 8:45 AM, Joao S. O. Bueno wrote:<br>
>> On 13 May 2013 22:55, Haoyi Li <<a href="mailto:haoyi.sg@gmail.com">haoyi.sg@gmail.com</a>> wrote:<br>
>>> I do not think expression soup is particularly bad, it's just Javascript's<br>
>>> implementation (as usual) that is pretty borked. In Scala, expression<br>
>>> chaining lets you do some pretty nice things:<br>
>>><br>
>>><br>
>>><br>
>>>      memory.take(freePointer)<br>
>>><br>
>>>            .grouped(10)<br>
>>><br>
>>>            .map(_.fold("")(_+"\t"+_))<br>
>>><br>
>>>            .reduce(_+"\n"+_)<br>
>><br>
>><br>
>> I hope you know that if you enjoy this style,<br>
>> Python _is_ for you, and I consider it part of the<br>
>> "multiparadigm" language.<br>
>><br>
>> You just have to design your methods to always return<br>
>> "self" - or make a class decorator to do so.<br>
>><br>
>> But in case you are using other people's classes<br>
>> an adaptor for methosds that woudl return "None"<br>
>> is easy to achieve.<br>
>><br>
>> I made this example a couple months ago to get it working:<br>
>><br>
>> class Chain:<br>
>>    def __init__(self, obj, root=None):<br>
>>        self.__obj = obj<br>
>>    def __getattr__(self, attr):<br>
>>        val = getattr(self.__obj, attr)<br>
>>        if callable(val):<br>
>>            self.__callable = val<br>
>>            return self<br>
>>        return val<br>
>>    def __call__(self, *args, **kw):<br>
>>        val = self.__callable(*args, **kw)<br>
>>        if val is None:<br>
>>            return self<br>
>>        return val<br>
><br>
> None val should not always be converted to self. Consider [None].pop(), where None is the real return, not a placeholder for no return.<br>
<br>
</div></div>I think this gets to a key issue.<br>
<br>
Chain is relying on the fact that all methods return something useful, or None. But None is something useful.<br>
<br>
This is a limitation that a language like Haskell doesn't have. You could have a "list of A" type whose methods all return "maybe A", meaning they return "Just something useful" or Nothing. In that case, Nothing is not something useful (but Just Nothing is).<br>


<br>
The benefit that comes along with this limitation is duck typing. We don't need a monad, type constructors, type deconstruction matching, and function-lifting functions because duck typing gets us 80% of the benefit for no effort. The downside is that we don't get that extra 20%. You don't have to build a lifting function when the need is implicit, but you _can't_ build a lifting function when you explicitly want it.<br>


<br>
I think that's a good tradeoff, but it is still a tradeoff.<br>
<br>
And Python's consistency is part of what makes it a good tradeoff. JavaScript has even more flexibility in this area, so in theory it should be even more powerful. But in practice, it's not. And that's because it doesn't have consistent rules that define the boundaries--instead of "mutators don't return", it's "some mutators return this, others return the argument, others don't return". So, where Python has problems with the other-20% side of its tradeoff, JavaScript has the same problems with the whole 100%, so it gets a lot less benefit out of the dynamic typing tradeoff.<br>


<div class="HOEnZb"><div class="h5"><br>
>> Which allows, for example:<br>
>><br>
>>>>> a = []<br>
>>>>> Chain(a).append(5).append(6).append(-1).sort().append(3)<br>
><br>
> Which either raises or does the wrong thing for list.pop<br>
><br>
>> <__main__.Chain object at 0x12b6f50><br>
>>>>> a<br>
>> [-1, 5, 6, 3]<br>
>><br>
>> And would work in your example as well, should you have a class with<br>
>> the desired methods.<br>
><br>
><br>
> _______________________________________________<br>
> Python-ideas mailing list<br>
> <a href="mailto:Python-ideas@python.org">Python-ideas@python.org</a><br>
> <a href="http://mail.python.org/mailman/listinfo/python-ideas" target="_blank">http://mail.python.org/mailman/listinfo/python-ideas</a><br>
_______________________________________________<br>
Python-ideas mailing list<br>
<a href="mailto:Python-ideas@python.org">Python-ideas@python.org</a><br>
<a href="http://mail.python.org/mailman/listinfo/python-ideas" target="_blank">http://mail.python.org/mailman/listinfo/python-ideas</a><br>
</div></div></blockquote></div><br></div>