[Python-ideas] Anonymous blocks (again):

Haoyi Li haoyi.sg at gmail.com
Tue May 14 19:34:39 CEST 2013


Andrew, I agree with 100% of what you said; you put it much more clearly
than I could.

#soapbox
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.

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").
#end soapbox

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


@sys.meta_path.append
@singleton
class ImportFinder(object):
    ...


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 imp.do_stuff(), it will use the overriding methods.

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.


On Tue, May 14, 2013 at 12:57 PM, Andrew Barnert <abarnert at yahoo.com> wrote:

> 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
> _______________________________________________
> Python-ideas mailing list
> Python-ideas at python.org
> http://mail.python.org/mailman/listinfo/python-ideas
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-ideas/attachments/20130514/8bfd361c/attachment-0001.html>


More information about the Python-ideas mailing list