-
Notifications
You must be signed in to change notification settings - Fork 36
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Alternative to the pipe syntax #52
Comments
|
syntax
I'd vote for option 2: it's less verbose (no need to keep repeating the from collections import OrderedDict
from typing import Callable, Concatenate, ParamSpec, TypeVar
from typing_extensions import Self
T = TypeVar("T")
P = ParamSpec("P")
CustomCombinatorT = TypeVar("CustomCombinatorT", bound="Stream")
class Stream:
def combine(
self,
combinator: Callable[Concatenate["Stream", P], CustomCombinatorT],
*args: P.args,
**kwargs: P.kwargs,
) -> CustomCombinatorT:
return combinator(self, *args, **kwargs)
def some_combinator(stream: Stream, arg1: int) -> Stream:
return stream
def invalid_combinator(stream: Stream) -> OrderedDict:
return OrderedDict()
class CustomStream(Stream):
def __init__(self, stream: Stream):
self.stream = stream
def some_custom_method(self, foo: str) -> Self:
return self
def to_custom_stream(stream: Stream) -> CustomStream:
return CustomStream(stream)
xs = (
Stream()
.combine(some_combinator, 10) # OK, returns Stream
.combine(to_custom_stream) # OK, returns CustomStream
.some_custom_method("a") # OK, custom method can now be called directly
.combine(
some_combinator, "foo"
) # doesn't type check, combinator args are type checked
.combine(
invalid_combinator
) # doesn't type check, returned type must inherit from Stream
) |
The current pipe
|
syntaxFor the reference, here's how a long pipeline looks once blackified:
The aiostream pipe syntax is often (and legitimately) seen as magical. Conceptually though, it's quite simple: the pipe combinators (in
aiostream.pipe.*
) are just curried and flipped version of the standard combinators (inaiostream.stream.*
). For instance:Moreover, the pipe syntax is simply defined as regular function composition:
Combining those two ideas, we get:
That's neat but we can't really expect to convince every one that uses aiostream that "it's not magical, it's simply curried and flipped combinators with syntactic sugar for function composition".
Another issue is that the pipe operator precedence does not play well with the await statement:
Alternative 1, the
toolz
wayFor the reference, here's how a long pipeline would look once blackified:
Pros:
Cons:
pipe
namespace for flipped combinatorspipe
function has to be added, and the name conflicts with thepipe
namespaceAlternative 2, the rust way
For the reference, here's how a long pipeline would look once blackified (the parentheses have to be added explicitly though):
Pros:
pipe
scope for flipped combinators, methods already do thatCons:
The text was updated successfully, but these errors were encountered: