# \[ANN\] Chevrons.jl: friendly \>\> chevron \>\> based data piping

**URL:** <https://discourse.julialang.org/t/ann-chevrons-jl-friendly-chevron-based-data-piping/126066>\
**Category:** Package Announcements\
**Tags:** piping\
**Created:** [February 19, 2025, 11:06am UTC](https://discourse.julialang.org/t/ann-chevrons-jl-friendly-chevron-based-data-piping/126066 "2025-02-19T11:06:51Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![cjdoris](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cjdoris/32/213133_2.png) [@cjdoris](https://discourse.julialang.org/u/cjdoris)\
**Post date:** [February 19, 2025, 11:06am UTC](https://discourse.julialang.org/t/ann-chevrons-jl-friendly-chevron-based-data-piping/126066/1 "2025-02-19T11:06:51Z")

</div>

# Announcing Chevrons.jl

I’ve made another package for chaining/piping data transformations together, similar to Chain.jl and Pipe.jl, stealing some of their ideas but with nicer `>>`-based syntax and REPL integration.

Here is a little example of using it with TidierData.jl:

```julia-repl
julia> using Chevrons, DataFrames, TidierData

julia> Chevrons.enable_repl() # magic to enable Chevrons syntax in the REPL

julia> df = DataFrame(name=["John", "Sally", "Roger"], age=[54, 34, 79], children=[0, 2, 4])
3×3 DataFrame
 Row │ name age children
     │ String Int64 Int64
─────┼─────────────────────────
   1 │ John 54 0
   2 │ Sally 34 2
   3 │ Roger 79 4

julia> df >> @filter(age > 40) >> @select(num_children=children, age)
2×2 DataFrame
 Row │ num_children age
     │ Int64 Int64
─────┼─────────────────────
   1 │ 0 54
   2 │ 4 79

```

What I particularly like about it:

- **Less repetititve:** You don’t need to write `@chain` or `@pipe` every time, you can annotate an entire function, script or module with `@chevrons` to get the `>>` syntax.
- **REPL integration** so you can use this syntax automatically.
- `>>` is **easier to type** than `|>`.
- **Side-effects** with `>>>`, similar to Chain.jl’s `@aside`, e.g. for logging intermediate values.

Quick comparison with similar packages:

| Feature | Chevrons.jl | Chain.jl | Pipe.jl |
| --- | --- | --- | --- |
| Piping syntax | ✔ (`>>`) | ✔ (`@chain`) | ✔ (`|>`) |
| Side effects | ✔ (`>>>`) | ✔ (`@aside`) | ❌ |
| Pipe backwards | ✔ (`<<`) | ❌ | ❌ |
| Recursive syntax | ✔ | ❌ | ❌ |
| REPL integration | ✔ | ❌ | ❌ |
| Line numbers on errors | ❌ | ✔ | ❌ |

---

<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:** [February 19, 2025, 11:56am UTC](https://discourse.julialang.org/t/ann-chevrons-jl-friendly-chevron-based-data-piping/126066/2 "2025-02-19T11:56:17Z")

</div>

Is this exclusive for `DataFrame`s, or does this also work with general piping of stuff? How does this deal with integers?

---

<div class="post-metadata">

**Author:** ![cjdoris](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cjdoris/32/213133_2.png) [@cjdoris](https://discourse.julialang.org/u/cjdoris)\
**Post date:** [February 19, 2025, 12:12pm UTC](https://discourse.julialang.org/t/ann-chevrons-jl-friendly-chevron-based-data-piping/126066/3 "2025-02-19T12:12:14Z")

</div>

Nope, it’s completely generic. Take a look at [the README](https://github.com/cjdoris/Chevrons.jl?tab=readme-ov-file#usage) for more examples, such as:

```julia-repl
julia> [5,2,4,3,1] >> filter!(isodd, _) >>> println("x = ", _) >> sum()
x = [5, 3, 1]
9

```

---

<div class="post-metadata">

**Author:** ![caleb-allen](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/caleb-allen/32/14054_2.png) [@caleb-allen](https://discourse.julialang.org/u/caleb-allen)\
**Post date:** [February 19, 2025, 1:18pm UTC](https://discourse.julialang.org/t/ann-chevrons-jl-friendly-chevron-based-data-piping/126066/4 "2025-02-19T13:18:03Z")

</div>

If I’ve enabled the REPL feature, is there a way to escape `>>` if I intend to call the bit shift operator? e.g.

```julia
julia> 10 >> 1
5

```

---

<div class="post-metadata">

**Author:** ![cjdoris](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cjdoris/32/213133_2.png) [@cjdoris](https://discourse.julialang.org/u/cjdoris)\
**Post date:** [February 19, 2025, 2:03pm UTC](https://discourse.julialang.org/t/ann-chevrons-jl-friendly-chevron-based-data-piping/126066/5 "2025-02-19T14:03:34Z")

</div>

Good question! You can do this by renaming the operator to something else and using it as an ordinary function:

```julia-repl
julia> using Base: << as lshift

julia> lshift(1, 10)
1024

```

I have [added this to the README](https://github.com/cjdoris/Chevrons.jl?tab=readme-ov-file#using-bit-shift-functions) thanks!

---

<div class="post-metadata">

**Author:** ![linwaytin](https://avatars.discourse-cdn.com/v4/letter/l/898d66/32.png) [@linwaytin](https://discourse.julialang.org/u/linwaytin)\
**Post date:** [February 19, 2025, 11:50pm UTC](https://discourse.julialang.org/t/ann-chevrons-jl-friendly-chevron-based-data-piping/126066/6 "2025-02-19T23:50:41Z")

</div>

This is a nice package. I really hope Julia can support syntax like this.  
However, I feel overwriting the `<<` and `>>` operators could be problematic. Why not considering other operators? I think julia have a bunch of unused operators.

---

<div class="post-metadata">

**Author:** ![StevenSiew](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevensiew/32/218393_2.png) [@StevenSiew](https://discourse.julialang.org/u/StevenSiew)\
**Post date:** [February 20, 2025, 12:35am UTC](https://discourse.julialang.org/t/ann-chevrons-jl-friendly-chevron-based-data-piping/126066/7 "2025-02-20T00:35:34Z")

</div>

I agree that getting rid of bitshift \<\< and \>\> would have meant that existing julia sourcecode could not work.

Please use another operators.

---

<div class="post-metadata">

**Author:** ![cjdoris](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cjdoris/32/213133_2.png) [@cjdoris](https://discourse.julialang.org/u/cjdoris)\
**Post date:** [February 20, 2025, 11:37am UTC](https://discourse.julialang.org/t/ann-chevrons-jl-friendly-chevron-based-data-piping/126066/8 "2025-02-20T11:37:08Z")

</div>

You have to opt-in to this syntax with the `@chevrons` syntax, so it won’t break existing code. It’s purely a syntactic change to code annotated with `@chevrons` and won’t affect functions that that code calls.

---

<div class="post-metadata">

**Author:** ![bertlhf](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bertlhf/32/38078_2.png) [@bertlhf](https://discourse.julialang.org/u/bertlhf)\
**Post date:** [February 26, 2025, 7:48pm UTC](https://discourse.julialang.org/t/ann-chevrons-jl-friendly-chevron-based-data-piping/126066/9 "2025-02-26T19:48:42Z")

</div>

> [@cjdoris](#):
>
> `Chevrons.enable_repl()`

Is there a way to use chevrons in a Pluto notebook without typing `@chevrons` in every cell?

---

<div class="post-metadata">

**Author:** ![cjdoris](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cjdoris/32/213133_2.png) [@cjdoris](https://discourse.julialang.org/u/cjdoris)\
**Post date:** [February 27, 2025, 10:43am UTC](https://discourse.julialang.org/t/ann-chevrons-jl-friendly-chevron-based-data-piping/126066/10 "2025-02-27T10:43:57Z")

</div>

Not currently. @fonsp does Pluto have any hooks that let us transform the AST of a cell before it is evaluated? (Would be cool to also have `Chevrons.enable_pluto()` or something.)
