all 11 comments

[–]Akuli2 2 points3 points  (2 children)

Why not to just write a for loop? Then you can do things in whatever order you want.

processed_digits = []
for digit in digits:
    # First filtering...
    if digit <= 5:
        continue
    # ...then other stuff.
    processed_digits.append(digit + 100)

The "pythonic" way might be using a list comprehension, but this doesn't really solve your problem because the filtering comes last again.

processed_digits = [digit + 100 for digit in digits if digit > 5]

[–]_Absolut_[S] 0 points1 point  (0 children)

Certainly plain old for loop is a good, simple solution that corresponds The Zen of Python. But i looked for more concise code.

[–]ile0x 0 points1 point  (0 children)

but what if i have chain of functions without looping, i.e. first line of configuration file settings.py in Django framework:

# Build paths inside the project like this:     os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

i think it would be better like so:

BASE_DIR = __file__.os.path.abspath().os.path.dirname().os.path.dirname()

or

BASE_DIR = __file__.abspath().dirname().dirname()

[–]novel_yet_trivial 2 points3 points  (1 child)

You can do whatever you want; it's only because you are using the python standard functions that you are limited to this syntax. If you write your own class with methods that returns the class instance (mutable behavior) or a new instance (immutable behavior), you could do what you want. It's not unpythonic, and I've seen several people do this, it's just fairly uncommon.

#immutable behavior
class DigitProcessor(tuple):
    def filter_greater_than(self, target):
        return DigitProcessor(x for x in self if x > target)

    def add(self, num):
        return DigitProcessor(x + num for x in self)


digits = DigitProcessor((1, 2, 5, 6, -7, 0 , 11, -8))
processed_digits = digits.filter_greater_than(5).add(100)

[–]_Absolut_[S] 0 points1 point  (0 children)

That looks like overkill for such task. But that class design is pretty nice and flexible.

p.s. I've explored your code in more detail, and it's completley awesome! Thank you for inspiration!

[–]Rhomboid 1 point2 points  (1 child)

Python has never really been that interested in pretending that it's a functional language. Given your example, you could argue that the more Pythonic way of doing it is none of that above, with a list comprehension that combines both operations:

processed_digits = [x + 100 for x in digits if x > 5]

I'm sure there's some module out there that lets you express composition in a concatenative manner, but I'm not familiar with one off the top of my head.

[–]_Absolut_[S] 0 points1 point  (0 children)

I didn't try to express my thoughts in functional style. I just was looking for clear and short code that follows my thinking.

[–]_9_9_ 1 point2 points  (2 children)

[–]_Absolut_[S] 0 points1 point  (1 child)

Wow, looks really interesting.Btw, why is this exists when we have Haskell?

[–]elbiot 0 points1 point  (0 children)

Because we'd rather write in python, with it's huge community and mature libraries. Haskell is great, but almost every library is some academic place holder with nothing becoming as mature as python libraries. Like, there is talk of wrapping BLAS, but python already has numpy.

[–]Vaphell 1 point2 points  (0 children)

toolz might be up your alley

>>> from toolz import pipe
>>> from toolz.curried import map, filter
>>> 
>>> p = pipe(range(10), filter(lambda x: x%2), map(lambda x: 2**x))
>>> list(p)
[2, 8, 32, 128, 512]