[Python-ideas] Anonymous blocks (again):

Andrew Barnert abarnert at yahoo.com
Tue May 14 18:57:03 CEST 2013


On May 14, 2013, at 8:22, Terry Jan Reedy <tjreedy at udel.edu> wrote:

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

I think this gets to a key issue.

Chain is relying on the fact that all methods return something useful, or None. But None is something useful.

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).

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.

I think that's a good tradeoff, but it is still a tradeoff.

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.

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


More information about the Python-ideas mailing list