Hacker News new | ask | show | jobs
by tandav 1101 days ago
shameless plug: I maintain a small library to do functional pipes.

You can write:

    (
        range(10)
        | Map(lambda x: x * 10)
        | Filter(lambda x: x % 2 == 0)
        | Reduce(lambda a, b: a + b)
    )
instead of:

    x = range(10)
    x = map(lambda x: x * 10, x)
    x = filter(lambda x: x % 2 == 0, x)
    x = reduce(lambda a, b: a + b, x)
and more. https://tandav.github.io/pipe21/
4 comments

    import pandas as pd
    import functools
    
    (
        pd.Series(range(10))
        .apply(lambda x: x * 10)
        .where(lambda x: x % 2 == 0)
        .pipe(lambda s: functools.reduce(lambda x, y : x + y, s))
    )
Readability isn't the best. Also what you present here is method chaining and not functional pipes.
What difference does it make? They're conceptually the same thing. You're mapping immutable data to map/reduce/filter like pure functions to get new data.
Improved code readability. The pipe operator was a game changer for me even after 20 years of programming (I know I was probably touching wrong things).
Is the difference mostly syntactic?
with dot chaining you are restricted to only the functions that the API you're working with provides. With functional pipes you can use whatever functions you want.
In this case, the API provides .pipe, with which you can then use whatever functions you want.
This looks cool! I always wanted something similar for pandas, because I found it very elegant in dplyr in R. AFAIK they do have a `.pipe` method now but it could definitely be better in the future.
Hmm, I've never seen code like the latter so it's unclear what problem this solves. I'd just write the pandas code snippet given below. Possibly with polars to make it lazy.
My library solves 2 problems.

1. It does not require to wrap your iterable into some wrapper to use functional methods. It takes an iterable/object and returns another iterable/object. You don't have to unwrap it after transformations.

2. it uses oneliners (library is 80LOC single file) for most of the methods. You can just copy-paste it to use instead of install and import. E.g map, filter, reduce is just:

    class B:
        def __init__(self, f): self.f = f
    class Pipe  (B): __ror__ = lambda self, x: self.f(x)
    class Map   (B): __ror__ = lambda self, x: map   (self.f, x)
    class Filter(B): __ror__ = lambda self, x: filter(self.f, x)
    class Reduce(B): __ror__ = lambda self, it: functools.reduce(self.f, it, *self.args)
It is a fairly common pattern in low level stuff like hashing algorithms or cryptography.
if folks like this and use JS, there is a very similar library for that ecosystem: https://ramdajs.com/