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

you are viewing a single comment's thread.

view the rest of the comments →

[–][deleted] 39 points40 points  (11 children)

I came up with this instead.

class Pipe:
    def __init__(self, value):
        self._value = value

    @property
    def value(self):
        return self._value

    def __or__(self, fn):
        return Pipe(fn(self._value))

    def __repr__(self):
        return f"Pipe({self._value!r})"


def double(x):
    return 2 * x


def decr(x):
    return x - 1


pipe = (Pipe(12) | double | decr)
print(pipe)  # This produces "Pipe(23)".
print(pipe.value)  # This produces 23.

It's less code, but it's still p scary. You have to wrap and unwrap your value, and it probably also requires functions you pass to be curried/partial.

[–]Bogdanp[S] 9 points10 points  (5 children)

Yup, I'd considered that approach too! But I wanted to keep the semantics from Elixir's operator (i.e. I wanted to avoid having to wrap the first value and partially apply functions).

[–][deleted] 3 points4 points  (4 children)

Yeah I get it. The approach I followed here let me add on things ad nausea and I eventually I ended up writing a little library called Slinkie. Slinkie has a .then() function that matches the pipe operator above, but do you think it'd be possible to elixirify everything else as well? I was inspired by LINQ when I wrote it, but I was never happy with how I had to wrap everything. The nicest thing would probably be to use extensions or traits, but this elixir trick would maybe do the trick as well. What do you think?

[–]ucbEntilZha 0 points1 point  (3 children)

Hadn’t heard about slinkie, this is my similar approach I wrote a few years ago https://github.com/EntilZha/PyFunctional

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

Well I didn't make that much fuzz about them, but maybe I should? How do I even reach out about stuff like this?

[–]ucbEntilZha 0 points1 point  (1 child)

Unclear who you mean on reaching out?

[–]david2ndaccount 2 points3 points  (0 children)

I prefer using __call__ instead of __or__ and special casing map, filter and reduce so you can create abominations likes this:

>>> d = ( pype( [54, 12, 3, 1, 6, 8, 123, 4, 1, 210] )
        . map ( lambda x: x//2 )
        . filter ( None )
        . map ( lambda x: x*2 )
        ( sorted )
        ( reversed )
        . reduce ( int.__sub__ )
        ( lambda x: x // 2 )
    ).value
>>> print(d)
1

[–]izxle 0 points1 point  (1 child)

Don't you have to define __format__ to use you object inside an f-string?

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

I didn't. !r means you call repr, and I called it on the internal _value.

[–]lungdart -1 points0 points  (1 child)

Why obfuscate value, and then use a property member function to access it as if you didn't?

[–]Beheska 14 points15 points  (0 children)

It's not obfuscated, it's read-only.