Skip to content
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

RFC: Add new pipe-like operator syntaxes </, |>>, etc. #34340

Open
wants to merge 5 commits into
base: master
Choose a base branch
from

Conversation

tkf
Copy link
Member

@tkf tkf commented Jan 10, 2020

This patch adds pipe-like operators such as </ and |>> (as requested in #25233) etc. All combinations of "heads" <, <<, >, and >> and "tails" |, / and \ are supported.

To increase the probability of this PR to be merged, I'd like to avoid implementing any interface in Base on top of these syntaxes here. But the motivating example is to have the opposite composition operator

/>(args...) = (reverse(args)...)

so that one can have

1 |> sin |> cos |> tan == 1 |> (sin /> cos /> tan)

This is useful when you have an interface where using successive |> is a natural way to call functions (e.g., Query.jl, Transducers.jl). Then, the pipeline part can be factored out by using the opposite composition operator />. For symmetry, it may be useful to define </ to be the usual composition operator. This would give us an ASCII alias of #33573. (Note: the associativity of </ and are different. But composition is associative so I think it's OK.) See discussion started at JuliaFolds/Transducers.jl#67 (comment) for more explanations on the motivation.

Another motivating usecase of a pipe-like operator |>> is discussed in #25233 and #34344.

cc @davidanthoff Maybe you are interested in new operators like this too?

@davidanthoff
Copy link
Contributor

Hm, to be honest, not clear to me that this is a high priority thing? At least from the Query.jl side of things I haven't missed it :) But I might be missing something deeper here.

I think if it gets added, it should have an implementation with it, otherwise I don't see how one can add consistent functionality to it without type piracy?

@tkf
Copy link
Member Author

tkf commented Jan 10, 2020

You can use operator names overlapping with Base without any piracy

julia> module MyModule
       *(args...) = foldr(Base.:*, args)
       end
Main.MyModule

julia> MyModule.:* === Base.:*
false

But yes, I guess I'll open a PR to add Base./> after this PR. I just want to minimize the patch to get this merged as fast as possible.

@tkf
Copy link
Member Author

tkf commented Jan 11, 2020

In #25233 (comment), @StefanKarpinski mentioned that operators like this can be added even though they are technically breaking due to

julia> :(_ />)
:(_ / (>))

julia> VERSION
v"1.3.1"

@tkf tkf changed the title RFC: Add new pipe-like operators </, <\, />, and \> RFC: Add new pipe-like operators </, |>>, etc. Jan 11, 2020
@JeffBezanson JeffBezanson added the triage This should be discussed on a triage call label Jan 13, 2020
@tkf tkf changed the title RFC: Add new pipe-like operators </, |>>, etc. RFC: Add new pipe-like operator syntaxes </, |>>, etc. Jan 15, 2020
@JeffBezanson
Copy link
Member

|>> is maybe ok, but I find the pipes with the slashes pretty confusing.

@tkf
Copy link
Member Author

tkf commented Jan 16, 2020

Why is it confusing? Do you mean it doesn't have | while it is listed in prec-pipe? Would it be OK if they are moved to other list (e.g., prec-times)? My motivation is to have some variants of |> (or more precisely anything usable as an ASCII opposite composition operator).

@JeffBezanson
Copy link
Member

They're confusing because they don't really visually convey to me what they do, nor are they used by any other system that I'm aware of.

@StefanKarpinski
Copy link
Member

This seems very syntax-greedy. We often find ourselves in the situation of needing syntax for something and every last bit of available possible syntax is valuable. Why is having this many pipelike operators a good way to spend syntax? Some of them I can see, but all of these? Really? You can't use functions or one of the billion Unicode operators that Julia supports?

Some other points from triage: other systems don't seem to support most of these—especially the slash and backslash variants—so this seems to be totally unprecedented operator territory. They're also just visually confusing to parse. This is veering deep in the Perl ASCII salad territory. When someone sees \>> why is "oh, that's a single operator" be obvious?

@davidanthoff
Copy link
Contributor

#34344 is a PR that only adds the |>> case, which is the part that I would like to see (mostly for Query.jl).

@tkf
Copy link
Member Author

tkf commented Jan 31, 2020

@StefanKarpinski

Why is having this many pipelike operators a good way to spend syntax? Some of them I can see, but all of these?

My primary motivation was to add one or two operators (say />). So I'm willing to reduce the number of operators in this PR if it increases the chance for it to be merged.

But since the parser allows <| even though Base does not have the definition of it, I thought to follow the same "convention" (though maybe I misread the intention) and define other operators for symmetry. By symmetry, I mean that once /> is introduced, it's strange that x /> is a syntax error while x </ is not. Another reasoning was to reduce future syntax breakage in case other combinations are needed; adding </ has the effect of making x </ a syntax error.

When someone sees \>> why is "oh, that's a single operator" be obvious?

But you don't see infix operators in isolation. If you see x />> y />> z, it's hard to not think that's an infix operator.

You can't use functions

As Dijkstra also noted, infix operator is great because you don't have to put parentheses. This is a strong indication that the operation is associative. Usual function call does not indicate this algebraic property.

or one of the billion Unicode operators that Julia supports?

Yes, it's great that Julia provides Unicode as a fallback option for situation like this. But I do hope that fundamental operations such as composition and opposite composition can be done with ASCII characters.


@JeffBezanson

They're confusing because they don't really visually convey to me what they do

I think /> and </ still convey a sense of directionality. Arguably this nuance is missing in more standard (and unfortunately non-ASCII) notations and ∘ᵒᵖ. I think /> and </ also visually similar to |> and <|. Also, by appearing at the infix position, they visually indicate that the operation is likely associative.

Other than that, I agree that it's impossible to infer the semantics of the operation. But I think it can be said for any less famous infix operators in programming.

nor are they used by any other system that I'm aware of.

I know similar operators <<< and >>> are defined in a Haskell library. Unfortunately, >>> is already defined in Julia. (Though I guess "Haskell has it" is not a convincing argument...)


If the concern is that /> does not look like a pipe operator, would it be better to introduce something like |->, |+>, |*>, or |%>? Operator |!> may make sense for #34344 to indicate that the operation is mutation or side-effect.

@yurivish
Copy link
Contributor

yurivish commented Jan 31, 2020

I don’t have an opinion on this issue, but I thought I would mention that the operators with slashes are strongly suggestive of HTML/XML to me.

@StefanKarpinski
Copy link
Member

If you see x />> y />> z, it's hard to not think that's an infix operator.

Sure. But when I see x/>>y/>>z I don't really see an infix operator. It's also entirely possible that there's some other syntax involving / and > that would currently be possible to add without breaking any code which the addition of this infix operator would prevent. It's possible that we could add these, but it's just not so clear-cut. There seems to be a common feeling that syntax is free and that there's no cost to adding new syntaxes, but there is a very real opportunity cost.

@tkf
Copy link
Member Author

tkf commented Feb 1, 2020

There seems to be a common feeling that syntax is free and that there's no cost to adding new syntaxes, but there is a very real opportunity cost.

I think I understand that ASCII syntaxes are real estates that should not be wasted and tweaking syntaxes in general is a one-way street. That's actually why I suggested adding all the combinations. Right now, a/>> is parsed as a / (>>) which is wasting the valuable ASCII syntax.

But, admittedly, this is not exactly the best "fix" in the sense we can be even more cautious. For example, maybe it's better to make consecutive operators without spaces between them a syntax error? Even if we don't use /> for pipe operator, it may be useful for something else in the future (e.g., for XML/HTML DSL like @yurivish just mentioned).

Also, I still would like to add one rightward pipe operator (to be used for opposite the composition operator) and, ideally, another leftward pipe operator that is the flip version of it. How about |-> (and <-|)?

@c42f
Copy link
Member

c42f commented Mar 28, 2020

This is pretty interesting. If we want a stronger visual analogy to piping which includes the | char, perhaps <<| and |>> would be good for composition rather than other uses.

With |>> for reverse composition we have

data |> (f |>> g |>> h)  ==
data |>  f |>  g |>  h

which has a nice symmetry. (There's also ||> and <|| as potential options?)

It might be good to emphasize again the mathematical point of view which unifies transducers and iterator transforms into a single category with left and right actions JuliaFolds/Transducers.jl#67 (comment). That seems like an important enough observation to justify some kind of syntax eventually.

A couple of other thoughts — somehow I find it troubling that vs <<| would have different associativity; unrelatedly I very much like the suggestion of |!> as side-effectful piping.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
triage This should be discussed on a triage call
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants