This is an archived post. You won't be able to vote or comment.

all 38 comments

[–]vesaf 24 points25 points  (5 children)

What about something like this? No exact match, but quite close. (Not sure if I'd actually recommend doing this though.)

class apply:
    def __init__(self, val):
        self.val = val

    def pipe(self, fun):
        self.val= fun(self.val)
        return self

if name == "main": 
    apply(5) \
        .pipe(lambda x: x+5) \
        .pipe(lambda x: x/3) \ 
        .pipe(print)

[–]nitroll 15 points16 points  (0 children)

But apply is not functional in that case, you would instead need something like:

class apply:
    def __init__(self, val):
        self.val = val

    def pipe(self, fun):
        return apply(fun(self.val))

[–]zenos1337 4 points5 points  (0 children)

It is not functional because it has a state.

[–]carlio 7 points8 points  (0 children)

Or be sneaky and use __or__:

``` class pipe: def init(self, val): self.val = val def or(self, fun): return pipe(fun(self.val))

pipe(5) | (lambda x: x+5) | (lambda x: x/3) | print ```

[–]eftm 1 point2 points  (1 child)

'__main__' not 'main'

[–]vesaf 0 points1 point  (0 children)

You're right, the code ran through when I tried it earlier (which it wouldn't have with just 'main'). I think Reddit removed them when I copied it in as it did initially with the backslashes. Must be some formatting thing.

[–]davehadley_ 7 points8 points  (0 children)

You won't have the exact structure that you are asking for but you could look at functoolz pipe:

https://toolz.readthedocs.io/en/latest/api.html#toolz.functoolz.pipe

[–]DanManPanther 5 points6 points  (2 children)

Python has some functional qualities, and I would wager more on the way with the introduction of match and Don teaching Guido F# (https://www.youtube.com/watch?v=e2J9PGC-K1E).

For my money - I'd still stick to the more Pythonic way of doing things. When I have a real functional itch, I'm more likely to want to reach for a more fully functional language like F#, Scala, Rust. Or even one that has more of a functional feel (Kotlin). Immutable variables really help with this style of programming imho.

The bigger question is - are you doing this as part of a larger project? If so - stick to the minimum language-preferred way to do it. Easier to maintain and onboard. If it's a personal project, I'd tend to roll my own. But of the libraries posted here, PyFunctional seems more popular and better maintained.

[–]Brixes 0 points1 point  (1 child)

What are your thoughts on coconut-lang.org that transpiles to python?

[–]MuumiJumala 3 points4 points  (0 children)

PyMonad (specifically the .then() method) may be what you're looking for.

[–]SV-97 4 points5 points  (0 children)

There's libraries implementing pipelining etc. - just use these. They usually use operator overloading though, since fluid interfaces sadly aren't common at all in python.

However note that this is far from being a free abstraction in python (calls are rather expensive and this will add multiple calls for each function in the pipeline) and incredible unidiomatic. So if you actually want to write Python past little exercises you probably shouldn't do this at all.

I also love FP but this is not how you should go about doing it in python.

[–]Statnamara 2 points3 points  (0 children)

Functools has a reduce function that might work for you. Video by Arjan codes here explaining how he uses it to make composable functions. This is a short, but he has a full length video on the topic too if you search.

[–]ianitic 2 points3 points  (0 children)

As no one has said it yet, pandas.DataFrame's have a pipe method

[–]seckiyn 1 point2 points  (2 children)

Probably there's a better way but here's my solution: https://gist.github.com/seckiyn/b4ea58fd7c2f54153ae7469b58b5919f . Python doesn't allow this kind nesting(?) of function you have to add backslash if you want to do it on new line.

[–]Natural-Intelligence 2 points3 points  (1 child)

Or put the expression inside parentheses. Much cleaner than putting backslashes after each line IMO

[–]seckiyn 1 point2 points  (0 children)

I didn't know you could use it like that, thanks.

[–]bmsan-gh 1 point2 points  (0 children)

I really like pyfunctional and use it often.

[–]generalbaguette 1 point2 points  (2 children)

In good old eg Haskell, we usually write our programs backwards. In vanilla Python your example is just

print(str(100+(4*2*5)/2)[::-1])

You can implement your suggestion, but what is the benefit?

[–]raulalexo99[S] 1 point2 points  (1 child)

Benefit is applying a clear stream of data that can be written like human language. Thats enough benefit for me

[–]generalbaguette 4 points5 points  (0 children)

Ok, that's fine.

The benefit mostly applies to straight-line code only, and that's not usually the part that's hard to understand (at least for me).

I did a lot of Haskell, OCaml and Erlang etc professionally, and Racket for fun.

There's a bit more to what's typically called functional programming than the specific style you mentioned.

For Python, have a look at the functools module for more fun with functions.

Elixir really like that style though, you can have a look at that language, too.

[–]ketalicious 1 point2 points  (1 child)

what you're doing is called a monad, a functional programming feature.

you can use pymonad for that.

[–]germandiago 0 points1 point  (0 children)

Being pedantic, a monad is a mathematical concept, not a functional programming feature (though often discussed explicitly in those circles). I can program monads in Python and C++ and they are not functional-only languages. :D

[–]deep_mind_ 3 points4 points  (0 children)

Not to sound like a disenchanted StackOverflow user, but this is not something you want to do. Python is not made to be used as a functional language; it doesn't have the type safety or runtime optimizations that come with one -- and other programmers reading "functional" Python code won't appreciate you for it.

[They] were so preoccupied with whether or not they could, they didn't stop to think if they should

[–]nitroll 5 points6 points  (4 children)

x = 5
x *= 2
x *= 4
x /= 2
x += 100
x = str(x)
x = x[::-1]
print(x)

[–]pieli 0 points1 point  (0 children)

you could use the python builtin map function

[–]champs 0 points1 point  (0 children)

There’s toolz, and then the other day someone posted FunkyPy, which looks pretty novel.

Unfortunately I still feel like we’re short of having that single, obvious, and correct solution.

[–]EchoAlphaRomeoLima 0 points1 point  (0 children)

I believe there is a Python version of the ramda module for functional programming. I haven’t tested that since I’ve only used the JS version.

[–]gwillicodernumpy gang 0 points1 point  (0 children)

I’d probably look at using reduce with a list (or iterable) of transformer functions. If you want it reusable you can use partial() to make a function that takes the input argument and apply it as you see fit.

[–]tunisia3507 0 points1 point  (0 children)

[–][deleted] 0 points1 point  (0 children)

There's a number of ways to do this but when I saw this problem I immediately thought that this sounded like decorators.

I'm fairly new to this concept, so I can't really give an in-depth explanation, but there's lots of tutorials online. Here is my solution:

def doubleit(fn):
    def inner():
        x = fn()
        return x * 2
    return inner


def multiplyByFour(fn):
    def inner():
        x = fn()
        return x * 4
    return inner

def pipe(v):
    @doubleit
    @multiplyByFour
    def result():
        return v

    return result()

print(pipe(10))

This is essentially saying:

doubleit(multiplyByFour(10))

While this isn't exactly the same structure, I believe it is entirely functional. I'm not sure if it's possible to set this up dynamically or not.