Hacker News new | ask | show | jobs
by JoshuaDavid 1064 days ago
Here you go:

    class WrappedList:
        _fns = [map, filter, min, max, all, any, len, list]

        def __init__(self, it):
            self.it = it

        def __getattr__(self, name):
            for fn in self._fns:
                if name == fn.__name__:
                    def m(*args, **kwargs):
                        result = fn(*args, self.it, **kwargs)
                        if hasattr(result, '__iter__'):
                            return self.__class__(result)
                        else:
                            return result
                    return m

        def unwrap(self):
            return self.it

This allows you to do stuff like

    WrappedList([1, 2, 3, 4]).filter(lambda x: x % 2 == 0).map(lambda x: x * 3).list().unwrap() # [6, 12]
    WrappedList([1, 2, 3, 4]).map(lambda x: x >= 5).any() # False
Deciding whether or not this is something you should do, rather than just something you can do, is left as an exercise for the reader.
5 comments

Python debugging is most sane when the code just tries to keep it simple. After thousands of pdb sessions I can say most people should not be allowed to do this kind of thing in real code!
With a small reminder that the pythonic way to do filter and map is even more readable - but it's limited in scope:

   [x * 3 for x in [1, 2, 3, 4] if x % 2 == 0]

with that said, I still love the general concept of chaining, and I use that style a lot where it is already convenient and popular - in pandas code.
And herein we see a weakness of Python: There is no way to get rid of the lambda lambda lambda, without actually naming things using def. Even though we are defining a pipeline of steps, still have to put up with syntactic clutter. Compare with threading/pipeline in other languages.
You could improve the speed a little bit (maybe) by doing something like:

    self._fns = {fn.__name__: fn for fn in [...]}
This may not be faster since the list is so short, but worth checking into
This reads so much better
If you actually think this code is better there's a real library that does this: https://github.com/EntilZha/PyFunctional.
One puzzling thing is that it uses backslash continuation in its examples. The most favoured style, IMO is to use ()'s for line continuation, maybe the author just doesn't know about those.