# Fixing the Piping/Chaining Issue (Rev 3)

**URL:** <https://discourse.julialang.org/t/fixing-the-piping-chaining-issue-rev-3/90836>\
**Category:** Internals & Design\
**Tags:** multithreading, syntax, piping, chaining, threading\
**Created:** [November 26, 2022, 2:50am UTC](https://discourse.julialang.org/t/fixing-the-piping-chaining-issue-rev-3/90836 "2022-11-26T02:50:46Z")\
**Posts on this page:** 20\
**Page:** 3

<div class="post-metadata">

**Author:** ![uniment](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/uniment/32/24532_2.png) [@uniment](https://discourse.julialang.org/u/uniment)\
**Post date:** [December 6, 2022, 11:56am UTC](https://discourse.julialang.org/t/fixing-the-piping-chaining-issue-rev-3/90836/41 "2022-12-06T11:56:47Z")

</div>

Quite creative, I like it!

> [@Jollywatt](#):
>
> The main selling point seems to be repurposing brace syntax `{ }` to be function composition _with built-in support for partial application_.
> 
> There is a lot more to this proposal, but I’m not so sure about the rest of it.
> 
> …
> 
> I also prefer `Chain.jl` ’s use of `_` as the anonymous argument over `it` or any alphanumeric name.

I think there’s a certain nuance that’s missing though, which is:

> [@Fixing the Piping/Chaining Issue](https://discourse.julialang.org/t/fixing-the-piping-chaining-issue/89654/144):
>
> I think the ultimate objective should be to ~~find~~ settle on a syntax which can be a proper part of the language, so that the effort to build out the other things that would depend on it can be justified.

Namely, I’m trying to create a concept which is as general as possible, and as a result, trying to avoid the behavior of threading the argument into a default position. Additionally, as has been expressed [previously](https://discourse.julialang.org/t/fixing-the-piping-chaining-issue-rev-3/90836/21), the use of `_` is somewhat wasteful, when within the local context it is possible to define new keywords—this would keep `_` free for use in partial application, as [PR #24990](https://github.com/JuliaLang/julia/pull/24990) proposes.

Indeed, if this proposal were to be accepted _and_ #24990 were accepted (which is my hope), then many of the expressions here could look closer to Chain.jl:

```julia
"chains".{
    split(_, "")
    _.^2
    join(_, "•")
    uppercase
}

```

> [@Jollywatt](#):
>
> Personally, I find `x |> {f, g}` better than `x.{f, g}`

The other points that this misses are: 1) creation of an unneeded lambda (increases compile time) and 2) operator precedence. It’s frequent for chains to be short sub-expressions inside larger ones (e.g., `arr.{filter(f, _), first}.a+1`), and the lower precedence of `|>` forces more of it to be placed within the chain, e.g. `arr |> {filter(f, _), first, it.a+1}`, which is clumsier. The high precedence of `.` is useful.

> [@Sukera](#):
>
> typing `{` on my german keyboard requires pressing ALTGR (on the right side of the spacebar) as well as `7` (`0` for `}`) in the number row (also on the right side of the keyboard).

Oh dear, now I understand the dislike for curly braces! 😅 How prevalent are such keyboards?

---

<div class="post-metadata">

**Author:** ![Barget](https://avatars.discourse-cdn.com/v4/letter/b/94ad74/32.png) [@Barget](https://discourse.julialang.org/u/Barget)\
**Post date:** [December 6, 2022, 12:34pm UTC](https://discourse.julialang.org/t/fixing-the-piping-chaining-issue-rev-3/90836/42 "2022-12-06T12:34:49Z")

</div>

> [@uniment](#):
>
> Oh dear, now I understand the dislike for curly braces! 😅 How prevalent are such keyboards?

As far as I know, belgian and french too…

---

<div class="post-metadata">

**Author:** ![uniment](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/uniment/32/24532_2.png) [@uniment](https://discourse.julialang.org/u/uniment)\
**Post date:** [December 6, 2022, 12:40pm UTC](https://discourse.julialang.org/t/fixing-the-piping-chaining-issue-rev-3/90836/43 "2022-12-06T12:40:33Z")

</div>

Another point I think bears re-emphasis:

A large motivation for pushing for acceptance as a language feature, is to get autocomplete support. Not only would this improve method discoverability as the OO folks have, but it would also make it so that threading into a default argument position (first for Chain.jl, last for DataPipes.jl) isn’t as compelling: for example, if this proposal and PR #24990 were accepted, then in `"1:2:3".{split(_, ":")}`, an autocomplete would likely fill out `(_, )` and place the cursor after the comma, saving the effort of typing the underscore.

(Before I catch flak for the compile time of constructing a partial applicator, in proposal #2 I proposed giving `_` preferred treatment within the chaining syntax so that it would be syntax-transformed into a simple function call. I didn’t restate that in this proposal, but I do still carry that intent. Perhaps I should code it in.)

As a result, I feel inclined to oppose the behavior of automatically threading into any default argument position, because the effort it saves would be negligible.

> [@Barget](#):
>
> As far as I know, belgian and french too…

This is not good. How do they manage C-style languages? And in Julia, are they much less inclined to use type parameterization?

I suppose if we went forward with this proposal, an autocomplete would become popular very quickly: when typing `obj.`, probably the first option to appear should be `obj.{}` so that these characters need not be typed. 😅 (of course, they’d be only entered if you hit \<tab\>.)

---

<div class="post-metadata">

**Author:** ![antoine-levitt](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/antoine-levitt/32/4008_2.png) [@antoine-levitt](https://discourse.julialang.org/u/antoine-levitt)\
**Post date:** [December 6, 2022, 12:41pm UTC](https://discourse.julialang.org/t/fixing-the-piping-chaining-issue-rev-3/90836/44 "2022-12-06T12:41:48Z")

</div>

> [@uniment](#):
>
> This is not good. How do they manage C-style languages?

we suffer.

---

<div class="post-metadata">

**Author:** ![Barget](https://avatars.discourse-cdn.com/v4/letter/b/94ad74/32.png) [@Barget](https://discourse.julialang.org/u/Barget)\
**Post date:** [December 6, 2022, 1:28pm UTC](https://discourse.julialang.org/t/fixing-the-piping-chaining-issue-rev-3/90836/45 "2022-12-06T13:28:44Z")

</div>

> [@uniment](#):
>
> This is not good. How do they manage C-style languages? And in Julia, are they much less inclined to use type parameterization?

Well, it’s not _that_ bad. For belgian, thumb and index at aligned (see link). But for french, indeed, that’s more painful …  
[Belgian keyboard layout](https://en.wikipedia.org/wiki/File:Belgian_keyboard_layout.png)  
[French keyboard layout](https://en.wikipedia.org/wiki/AZERTY#/media/File:KB_France.svg)  
Bottom line, keep in mind the vast majority of languages use curly braces, and this doesn’t prevent these countries (Germany, France, Belgium, other …) to code in e.g. javascript / C / Go / etc. … 🙃

---

<div class="post-metadata">

**Author:** ![sijo](https://avatars.discourse-cdn.com/v4/letter/s/da6949/32.png) [@sijo](https://discourse.julialang.org/u/sijo)\
**Post date:** [December 6, 2022, 1:49pm UTC](https://discourse.julialang.org/t/fixing-the-piping-chaining-issue-rev-3/90836/46 "2022-12-06T13:49:57Z")

</div>

I did too, until I decided to do all coding with a US keyboard layout. It works well because in code files I write everything in English anyway. And every OS has a standard keyboard shortcut to switch layout for writing documents in French/German/etc. I’m much happier ever since, also having less strain in my fingers when coding.

---

<div class="post-metadata">

**Author:** ![Palli](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/palli/32/3380_2.png) [@Palli](https://discourse.julialang.org/u/Palli)\
**Post date:** [December 6, 2022, 2:04pm UTC](https://discourse.julialang.org/t/fixing-the-piping-chaining-issue-rev-3/90836/47 "2022-12-06T14:04:56Z")

</div>

[Off-topic? I.e. this post, as some others, only about typing on different keyboards, e.g. braces.]

That applies to e.g. the Icelandic keyboard too! For me at least it feel very natural to type in { and }. I suppose if people opposed very much Java, C and C++ and other curly-brace languages wouldn’t be popular (in Germany and some places)…

You do get people occasionally asking for this in Julia instead of begin … end. I’m very pro on not doing that (and it will not happen), not because of your objection, but it’s more useful for other things. Would this new syntax be most useful way of explaining those brackets?

> [@Sukera](#):
>
> That’s more difficult to type than `@` or `|>`

Well @ for me is AltGr and Q so not easier to type with one hand… (I never understood why the other Alt no [allowed to] working, since it does nothing) as I type the braces. I suppose with two hands as I do slightly easier than the braces with one (or two hands, if I were to adjust to doing that).

> [@Barget](#):
>
> it’s not _that_ bad. For Belgian

Wow, that’s an awful (looking, e.g. for M) keyboard, with `(` typed as, I suppose AltGR and, 5 (plus it being AZERTY, at least odd to me); or maybe not I guess you no longer for for using one hand (which was my first thought when responding, since I’m used to that).

---

<div class="post-metadata">

**Author:** ![adienes](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/adienes/32/37459_2.png) [@adienes](https://discourse.julialang.org/u/adienes)\
**Post date:** [December 6, 2022, 3:11pm UTC](https://discourse.julialang.org/t/fixing-the-piping-chaining-issue-rev-3/90836/48 "2022-12-06T15:11:15Z")

</div>

I agree with this summary. I would be curious to see the reception of the simplest parts of this, which is more or less “`Chain.jl` but with braces,” and with the differences you propose since I also prefer each of those, submitted as an actual PR into Base. It seems there is sometimes a different nature of discussion that happens on GitHub than on Discourse.

---

<div class="post-metadata">

**Author:** ![Barget](https://avatars.discourse-cdn.com/v4/letter/b/94ad74/32.png) [@Barget](https://discourse.julialang.org/u/Barget)\
**Post date:** [December 6, 2022, 3:48pm UTC](https://discourse.julialang.org/t/fixing-the-piping-chaining-issue-rev-3/90836/49 "2022-12-06T15:48:42Z")

</div>

> [@Jollywatt](#):
>
> ```julia
> julia> "chains" |> {
> split("")
> _ .^ 2
> join("•")
> uppercase
> }
> 
> ```

I like this approach very much … exepct the REPL customization part, which makes it non-easily reproducible / deployable. But it’s understandable due to its sheer experimental nature.

Building on top of that, I was considering that maybe a more Julian-consistent syntax could be

```julia
julia> "chains" pipe
           split("")
           _ .^ 2
           join("•")
           uppercase
       end

```

… where `pipe` (or similar) should be a reserved keyword, such as `let`, `begin`, `do`, etc.

---

<div class="post-metadata">

**Author:** ![Sukera](https://avatars.discourse-cdn.com/v4/letter/s/ce7236/32.png) [@Sukera](https://discourse.julialang.org/u/Sukera)\
**Post date:** [December 6, 2022, 5:30pm UTC](https://discourse.julialang.org/t/fixing-the-piping-chaining-issue-rev-3/90836/50 "2022-12-06T17:30:41Z")

</div>

> [@Barget](#):
>
> Bottom line, keep in mind the vast majority of languages use curly braces, and this doesn’t prevent these countries (Germany, France, Belgium, other …) to code in e.g. javascript / C / Go / etc. … 🙃

And it also doesn’t prevent us from developing carpal tunnel due to that 😉 We can’t change existing languages, but I’d rather not repeat the mistakes of the past when other solutions already exist.

A bit offtopic, but if you’ve ever wondered why Vim uses the ESC key for so many operations even though it’s very far out of the way - on the keyboard it was developed on, it was very accessible:

 ![](https://global.discourse-cdn.com/julialang/original/3X/2/8/28d69a4193581625b15c7ee21941a4fc1a161d54.jpeg)  
Also note the easy-to-press curly braces and pipe symbol (both left-shift+KEY (right-shift works too, but left-shift makes it once again easier with both hands)), which just aren’t an as prevalent thing on other keyboards…

---

<div class="post-metadata">

**Author:** ![uniment](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/uniment/32/24532_2.png) [@uniment](https://discourse.julialang.org/u/uniment)\
**Post date:** [December 7, 2022, 5:01am UTC](https://discourse.julialang.org/t/fixing-the-piping-chaining-issue-rev-3/90836/51 "2022-12-07T05:01:24Z")

</div>

If anything, the discussion over the last few comments has made me happier about the constraint to have the `.` dot in `x.{f, g}`, as it offers information for an autocomplete to fill in the curly braces `{}`. 😅

> [@Barget](#):
>
> I was considering that maybe a more Julian-consistent syntax could be
> 
> ```julia
> "chains" pipe
> ...
> end
> 
> ```
> 
> … where `pipe` (or similar) should be a reserved keyword

That seems like an interesting idea. I would avoid it for short chains, e.g. `arr.{first}.b[end]`, but for multi-line expressions it could be nice to have a more verbose syntax. This would be consistent with how the expression `(a; b)` is equivalent to the block expression `begin a; b end`.

I don’t know enough about parser design to know how difficult this would be to add to the language. But I like the idea.

---

<div class="post-metadata">

**Author:** ![Jollywatt](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jollywatt/32/202198_2.png) [@Jollywatt](https://discourse.julialang.org/u/Jollywatt)\
**Post date:** [December 7, 2022, 6:54am UTC](https://discourse.julialang.org/t/fixing-the-piping-chaining-issue-rev-3/90836/52 "2022-12-07T06:54:08Z")

</div>

> [@uniment](#):
>
> I would avoid [block syntax] for short chains, e.g. `arr.{first}.b[end]`, but for multi-line expressions it could be nice to have a more verbose syntax.

In my opinion, not being worth it for small chains is an advantage. It would encourage people to just write

```
b(first(arr))[end]

```

plainly. Suddenly having a short, alternative spelling like `a.{length}` for every function call `length(a)` would inevitably lead to unfortunate bifurcation of style across the Julia codebase, if it were to become syntax.

Don’t let me shoot you down, though. I realise `x.{f}` is more amenable to autocompletion, etc. (And this objection doesn’t apply if it were just inside a macro.)

---

<div class="post-metadata">

**Author:** ![uniment](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/uniment/32/24532_2.png) [@uniment](https://discourse.julialang.org/u/uniment)\
**Post date:** [December 7, 2022, 8:09am UTC](https://discourse.julialang.org/t/fixing-the-piping-chaining-issue-rev-3/90836/53 "2022-12-07T08:09:55Z")

</div>

> [@Jollywatt](#):
>
> Suddenly having a short, alternative spelling like `a.{length}` for every function call `length(a)` would inevitably lead to unfortunate bifurcation of style across the Julia codebase, if it were to become syntax.

I suspect this might be one of the bigger hurdles: overcoming the notion that it’s simply “not Julian” to place the function name in suffix position instead of prefix position, or that accommodating two styles would be too confusing.

Maybe I’m just an optimist, but I don’t think it’s bad. I see it as similar to how we are free to say, “he measured the length of the baby” `length(a)` or equivalently “he measured the baby’s length” `a.{length}`. The latter might invoke an image of a man with a baby, pulling out a measuring tape; while the former might invoke an image of a man with a measuring tape, stumbling across a baby to measure. They could both be true at various instants, but the one we go with is whichever makes more sense in the context.

(and using the pipe operator `a |> length` is like saying, “he took the baby and fed it into a length measuring machine.” 😆)

> [@Jollywatt](#):
>
> And this objection doesn’t apply if it were just inside a macro.

Indeed, many things about this proposal would be easier if I simply settled on releasing a macro. 😅 My fear is that, if all I do is release a macro, then there is insufficient motivation for someone to develop an autocomplete that leverages it.

---

<div class="post-metadata">

**Author:** ![jules](https://avatars.discourse-cdn.com/v4/letter/j/41988e/32.png) [@jules](https://discourse.julialang.org/u/jules)\
**Post date:** [December 7, 2022, 8:50am UTC](https://discourse.julialang.org/t/fixing-the-piping-chaining-issue-rev-3/90836/54 "2022-12-07T08:50:38Z")

</div>

Regarding non-Julian things, I considered at the time to have `@chain x { ... }` but decided against it because it seemed bad to introduce a competitor block syntax to `begin end` in a macro I could see used widely across the ecosystem, just to save a few characters. Which was the same reason I called it `@chain` and not something more cryptic like `@>` or other options. I thought that would make it easier to search for as well if you didn’t know the macro.

---

<div class="post-metadata">

**Author:** ![jar1](https://avatars.discourse-cdn.com/v4/letter/j/c0e974/32.png) [@jar1](https://discourse.julialang.org/u/jar1)\
**Post date:** [December 7, 2022, 9:01am UTC](https://discourse.julialang.org/t/fixing-the-piping-chaining-issue-rev-3/90836/55 "2022-12-07T09:01:39Z")

</div>

Personally I think `{ ... }` would be ideal to replace all the `... end` blocks in Julia. `begin end` is way too long for common block macros like chain, but IMO its replacement could be general to all macros, rather than privileging the chain use case.

---

<div class="post-metadata">

**Author:** ![aplavin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/aplavin/32/222056_2.png) [@aplavin](https://discourse.julialang.org/u/aplavin)\
**Post date:** [December 7, 2022, 10:31am UTC](https://discourse.julialang.org/t/fixing-the-piping-chaining-issue-rev-3/90836/56 "2022-12-07T10:31:48Z")

</div>

let-end is a bit shorter than begin (:  
DataPipes supports both (begin and let) for pipes, with corresponding differences in variable scopes.  
The let-end semantics is arguably much more common and natural in this context, begin-end is only for cases when multiple variables are defined in the pipe and used later outside of it.

---

<div class="post-metadata">

**Author:** ![adienes](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/adienes/32/37459_2.png) [@adienes](https://discourse.julialang.org/u/adienes)\
**Post date:** [December 7, 2022, 2:45pm UTC](https://discourse.julialang.org/t/fixing-the-piping-chaining-issue-rev-3/90836/57 "2022-12-07T14:45:22Z")

</div>

so proposal 4 I am seeing scattered over a few comments: do all of the following

1. merge #24990 to get underscore partial application
2. merge `Chain.jl` into Base with three changes  
a. make `@chain` no longer thread automatically into first argument  
b. change `@chain x begin ... end` semantics to simply `x chain ... end` or `x pipe end`  
c. (maybe?) allow links in the chain to be separated by commas or pipes than only newline

---

<div class="post-metadata">

**Author:** ![Barget](https://avatars.discourse-cdn.com/v4/letter/b/94ad74/32.png) [@Barget](https://discourse.julialang.org/u/Barget)\
**Post date:** [December 7, 2022, 4:48pm UTC](https://discourse.julialang.org/t/fixing-the-piping-chaining-issue-rev-3/90836/58 "2022-12-07T16:48:36Z")

</div>

FWIW, getting just 1 & 2 even without change would be already great (I find the syntax proposed by Chain.jl it already useful) 🙂

Also,with 2.b) I realise the way to capture the output is not obvious. So at least, this aspect should be carefully thought through.

---

<div class="post-metadata">

**Author:** ![adienes](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/adienes/32/37459_2.png) [@adienes](https://discourse.julialang.org/u/adienes)\
**Post date:** [December 7, 2022, 5:26pm UTC](https://discourse.julialang.org/t/fixing-the-piping-chaining-issue-rev-3/90836/59 "2022-12-07T17:26:32Z")

</div>

> [@Barget](#):
>
> I realise the way to capture the output is not obvious

maybe `x |> chain ... end` is better

---

<div class="post-metadata">

**Author:** ![uniment](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/uniment/32/24532_2.png) [@uniment](https://discourse.julialang.org/u/uniment)\
**Post date:** [December 7, 2022, 6:05pm UTC](https://discourse.julialang.org/t/fixing-the-piping-chaining-issue-rev-3/90836/60 "2022-12-07T18:05:53Z")

</div>

@jar1: We already have a shorter alternative to `begin a; b end` for blocks: `(a; b)` 😉

@jules: Appreciated. Considering that `{...}` parses differently than blocks anyway, that was a good move imo.

I do like the idea of having a more-verbose block syntax for multi-line `{...}`. Is there any analogy here? I don’t believe I’ve encountered any more-verbose block syntax for `[...]`.

> The let-end semantics is arguably much more common and natural in this context

@aplavin: I agree, I don’t like side-effects here; that’s why I’ve chosen to make `x.{f, g}` mean `let it=x; it=f(it); it=g(it); it end`.

This also makes its scope behavior consistent when you say: `chain={f, g}; x.{chain}`, because `{f, g}` means `it->(it=f(it); it=g(it); it)`

I’ve actually even gone a step further, and made it so that any local assignments have the `local` keyword prepended—that’s how much I dislike side effects 😅

@adienes and @Barget: The thing you must understand, is that the behavior of underscores in PR#24990 is incompatible with their behavior in Chain.jl. For example, PR#24990 would propose that `map(_^2, _)` should create a function that behaves like `x->map(y->y^2, x)`, whereas Chain.jl treats it as if it’s `x->map(x^2, x)`.

You have two possible paths:

1. Adopt underscore behavior like Chain.jl, which then makes it impossible to use `_` for partial application (at least, if we are to demand any consistency in language behavior).

2. Adopt underscore behavior like PR#24990. This allows underscore partial application both inside- and outside-of chains.

You choose path (2), as it offers the ability to write `_+1` instead of `Base.Fix2(+, 1)`, as well as opening up all sorts of other partial application applications (e.g. if a function composition fallback [is implemented](https://discourse.julialang.org/t/fixing-the-piping-chaining-partial-application-issue-rev-2/90408/7), you could write `filter(_%3==0, arr)`).

However, you soon run into the problem that you can’t make expressions where the same variable appears more than once: `_+_^2` doesn’t behave as `x->x+x^2` and instead throws an error. But you say, “This is a chain! Of course I meant the result of the last expression!”

You might go back and decide that you prefer (1). But that would prevent partial application syntax outside of chains, and you would burn `_` on something which didn’t need it (remember that we’re creating a new context, in which we are at liberty to choose new keywords!).

So then you say, okay. Let’s choose path (2), and select a local keyword. You survey the landscape of identifiers. You consider `⬚`, but it’s difficult to type. Then you realize, singular non-gendered object pronouns carry _the exact meaning that you are after here_. So then you arrive at `it`, and the exact behaviors of this proposal.

Which brings us back to:

> [@uniment](#):
>
> Can you explain your reasoning for continuing to oppose it, so I can better understand your viewpoint?

[Previous page](https://discourse.julialang.org/t/fixing-the-piping-chaining-issue-rev-3/90836.md?page=2)

[Next page](https://discourse.julialang.org/t/fixing-the-piping-chaining-issue-rev-3/90836.md?page=4)
