# Something Like Pipe Forward In Racket?

**URL:** <https://racket.discourse.group/t/something-like-pipe-forward-in-racket/3492>\
**Category:** General\
**Tags:** question\
**Created:** [January 14, 2025, 4:38pm UTC](https://racket.discourse.group/t/something-like-pipe-forward-in-racket/3492 "2025-01-14T16:38:16Z")\
**Posts on this page:** 15\
**Page:** 1

<div class="post-metadata">

**Author:** ![OldDutchCap](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/olddutchcap/32/2037_2.png) [@OldDutchCap](https://racket.discourse.group/u/OldDutchCap)\
**Post date:** [January 14, 2025, 4:38pm UTC](https://racket.discourse.group/t/something-like-pipe-forward-in-racket/3492/1 "2025-01-14T16:38:16Z")

</div>

Is there anything in Racket like the pipe forward operator (|\>) that I've seen in Haskell, F# and Elixir?

For those unfamiliar with this operator it simply passes the output of one function as the input to the next. So this:

(f (g x))

Would become this:

(f x) |\> g

Or something like that. I tried creating it myself but no doubt | is reserved for other purposes in Racket. And I'd really like to have it because it can simplify nested calls quite a bit! I'm sure others have already built something like this but I'm not sure what to google for hence I ask here.

---

<div class="post-metadata">

**Author:** ![soegaard](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/soegaard/32/19_2.png) [@soegaard](https://racket.discourse.group/u/soegaard)\
**Post date:** [January 14, 2025, 4:57pm UTC](https://racket.discourse.group/t/something-like-pipe-forward-in-racket/3492/2 "2025-01-14T16:57:11Z")

</div>

There are a couple of libraries for that.  
Here is one.

## Threading Macros

Alexis King

> **[Threading Macros](https://docs.racket-lang.org/threading/index.html)**

Also, checkout QI.

---

<div class="post-metadata">

**Author:** ![EmEf](https://avatars.discourse-cdn.com/v4/letter/e/53a042/32.png) [@EmEf](https://racket.discourse.group/u/EmEf)\
**Post date:** [January 14, 2025, 5:00pm UTC](https://racket.discourse.group/t/something-like-pipe-forward-in-racket/3492/3 "2025-01-14T17:00:27Z")

</div>

Do you mean this:

```scheme

racket

Welcome to Racket v8.15.0.12 [cs].

> (require threading)

> (~> 1 add1 sub1)

1

```

Also check out Qi

[https://docs.racket-lang.org/qi/index.html](https://docs.racket-lang.org/qi/index.html)

---

<div class="post-metadata">

**Author:** ![countvajhula](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/countvajhula/32/65_2.png) [@countvajhula](https://racket.discourse.group/u/countvajhula)\
**Post date:** [January 14, 2025, 5:07pm UTC](https://racket.discourse.group/t/something-like-pipe-forward-in-racket/3492/4 "2025-01-14T17:07:10Z")

</div>

Yes, try [Qi](https://docs.racket-lang.org/qi/index.html)!

```scheme
(require qi)
(~> (3) sqr add1) ; => 10

```

And btw yes, `|` is reserved -- it's used to [read some characters literally](https://docs.racket-lang.org/reference/reader.html#%28idx._%28gentag._3._%28lib._scribblings%2Freference%2Freference..scrbl%29%29%29), without any special meaning those characters might otherwise have while `read`ing the input. Racket is an S-expression / symex-oriented language, meaning that almost everything has the syntax `(f x ...)`, where `f` is either a function or a macro. So although you could implement a rule like what you had there:

```scheme
(f x) |> g --> (f (g x))

```

... it would need to be done as a [reader extension](https://docs.racket-lang.org/reference/Reader_Extension.html) (relatively rare) and not as a simple macro (very common and easy). Since S-expressions are such a versatile and explicit syntax, it's easy to write extensions to the language as rules transforming one S-expression to another and these are what we call macros. Qi is one such implementation of this behavior as a macro. The [threading macro](https://docs.racket-lang.org/threading/index.html) is another.

---

<div class="post-metadata">

**Author:** ![damien\_mattei](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/damien_mattei/32/2706_2.png) [@damien\_mattei](https://racket.discourse.group/u/damien_mattei)\
**Post date:** [January 14, 2025, 6:09pm UTC](https://racket.discourse.group/t/something-like-pipe-forward-in-racket/3492/5 "2025-01-14T18:09:23Z")

</div>

As previously answered it needs a reader extension or external parser and use a library (treading macro or Qi)

You can use as reader extension [SRFI 105 curly infix](https://github.com/damien-mattei/SRFI-105-for-Racket), i have implemented one for Racket, but for now ( see note below) it is simpler to use [Scheme+ for Racket](https://github.com/damien-mattei/Scheme-PLUS-for-Racket)

here is the running example:

```scheme
Welcome to DrRacket, version 8.14 [cs].
Language: reader SRFI-105, with debugging; memory limit: 8192 MB.
SRFI-105 Curly Infix parser for Racket Scheme and R6RS by Damien MATTEI
(based on code from David A. Wheeler and Alan Manuel K. Gloria.)

(require threading)

{1 ~> add1 ~> sub1}
1

{2 + {1 ~> add1 ~> sub1}}
3

'{(f x) ~> g}
'(~> (f x) g)

{3 ~> sqr ~> add1}
10

{3 ~> sub1 ~> sqr ~> add1}
5

```

note: normally only SRFI 105 is enought to have some infix notation if you enabled :

```scheme
(define srfi-strict #t) ; enable strict compatibility with SRFI 105

```

in the source code. (for now it is set to #f)

Note also that in an infix expression the new operator `~>` should have a defined an operator precedence rule.

Then the same syntax with ( ) instead of { } could be used.

All that are interesting ideas , i will put them in the next release of Scheme+.

---

<div class="post-metadata">

**Author:** ![damien\_mattei](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/damien_mattei/32/2706_2.png) [@damien\_mattei](https://racket.discourse.group/u/damien_mattei)\
**Post date:** [January 14, 2025, 6:19pm UTC](https://racket.discourse.group/t/something-like-pipe-forward-in-racket/3492/6 "2025-01-14T18:19:23Z")

</div>

> [@countvajhula](#):
>
> `(~> (3) sqr add1)`

works also with Qi:

```scheme
(require qi)
{(3) ~> sqr ~> add1}
10

```

---

<div class="post-metadata">

**Author:** ![shawnw](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/shawnw/32/1031_2.png) [@shawnw](https://racket.discourse.group/u/shawnw)\
**Post date:** [January 14, 2025, 7:37pm UTC](https://racket.discourse.group/t/something-like-pipe-forward-in-racket/3492/7 "2025-01-14T19:37:19Z")

</div>

[`compose1`](https://docs.racket-lang.org/reference/procedures.html#%28def._%28%28lib._racket%2Fprivate%2Flist..rkt%29._compose1%29%29) works too:

```scheme
> ((compose1 add1 sqr) 3)
10

```

---

<div class="post-metadata">

**Author:** ![OldDutchCap](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/olddutchcap/32/2037_2.png) [@OldDutchCap](https://racket.discourse.group/u/OldDutchCap)\
**Post date:** [January 14, 2025, 8:17pm UTC](https://racket.discourse.group/t/something-like-pipe-forward-in-racket/3492/8 "2025-01-14T20:17:27Z")

</div>

Wow so many good answers on this thread! Thanks to all of you for your advice!

I like typed racket (along with what I've seen of Qi) so I sort of combined them in this little example:

```scheme
#lang typed/racket

(require qi)

(define (times-ten [n : Number]) (* n 10))
(define (turn-to-string [n : Number]) (number->string n))

(define (demonstrate-qi [n : Number]) (~> (n) times-ten turn-to-string))

```

Just in case anyone else is curious.

---

<div class="post-metadata">

**Author:** ![benknoble](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/benknoble/32/16_2.png) [@benknoble](https://racket.discourse.group/u/benknoble)\
**Post date:** [January 14, 2025, 9:39pm UTC](https://racket.discourse.group/t/something-like-pipe-forward-in-racket/3492/9 "2025-01-14T21:39:37Z")

</div>

Just beware that some Qi flows may not combine well with TR—there's not a "typed Qi" and macros are especially prone to TR issues. See [https://github.com/drym-org/qi/issues/18](https://github.com/drym-org/qi/issues/18)

(As much as I love Qi, the threading package doesn't suffer as much from this problem because it performs a direct textual rewrite. Qi is structured more as a compiler of a complex DSL, so you can split the specification `(flow (~> times-ten turn-to-string))` from the application `(… n)`; this means it produces output that is harder for TR to reason about.)

---

<div class="post-metadata">

**Author:** ![OldDutchCap](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/olddutchcap/32/2037_2.png) [@OldDutchCap](https://racket.discourse.group/u/OldDutchCap)\
**Post date:** [January 14, 2025, 9:52pm UTC](https://racket.discourse.group/t/something-like-pipe-forward-in-racket/3492/10 "2025-01-14T21:52:18Z")

</div>

Yeah that's why I worked up that example; was wondering if Qi could work with TR. I guess I just happened to find a case that didn't cause that issue! Thanks for making me aware of that little potential landmine.

---

<div class="post-metadata">

**Author:** ![hendrikboom3](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/hendrikboom3/32/2748_2.png) [@hendrikboom3](https://racket.discourse.group/u/hendrikboom3)\
**Post date:** [January 14, 2025, 11:15pm UTC](https://racket.discourse.group/t/something-like-pipe-forward-in-racket/3492/11 "2025-01-14T23:15:44Z")

</div>

Or use parendown.

( f #/ g x )  
gets read as  
(f (g x))

It doesn't even matter what f, g, or x are.  
It's just notation.

[https://docs.racket-lang.org/parendown/index.html](https://docs.racket-lang.org/parendown/index.html)

-- hendrik

---

<div class="post-metadata">

**Author:** ![countvajhula](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/countvajhula/32/65_2.png) [@countvajhula](https://racket.discourse.group/u/countvajhula)\
**Post date:** [January 15, 2025, 1:03am UTC](https://racket.discourse.group/t/something-like-pipe-forward-in-racket/3492/12 "2025-01-15T01:03:14Z")

</div>

To add to what Ben said, it would be wonderful to support typed behavior with Qi, whether that's finding ways to interoperate better with Typed Racket, or developing a typed variant of Qi (which may also play well with TR). There have been a few community members who have expressed interest in this, so maybe with enough data and ideas, it would be feasible to make meaningful progress here. For the moment, if you continue to experiment along these lines, it would be valuable if you could share any experiences or desires (e.g., by reporting them on the Typed Qi issue linked above, or as a new issue).

---

<div class="post-metadata">

**Author:** ![OldDutchCap](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/olddutchcap/32/2037_2.png) [@OldDutchCap](https://racket.discourse.group/u/OldDutchCap)\
**Post date:** [January 15, 2025, 2:02pm UTC](https://racket.discourse.group/t/something-like-pipe-forward-in-racket/3492/13 "2025-01-15T14:02:56Z")

</div>

I'm happy to experiment! I don't believe I know enough about TR, Qi or Racket in general to contribute fixes for problems (yet) but I suppose trying things out and reporting issues I find is also helpful right?

---

<div class="post-metadata">

**Author:** ![countvajhula](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/countvajhula/32/65_2.png) [@countvajhula](https://racket.discourse.group/u/countvajhula)\
**Post date:** [January 16, 2025, 3:42am UTC](https://racket.discourse.group/t/something-like-pipe-forward-in-racket/3492/14 "2025-01-16T03:42:54Z")

</div>

Yes, absolutely! Giving something a name gives us power, etc. 🙂

Btw, with help from some kind folks on Discord, there have been some [small steps towards interoperability with TR](https://github.com/drym-org/qi/pull/191). I don't know how close we can get, but let's see.

---

<div class="post-metadata">

**Author:** ![countvajhula](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/countvajhula/32/65_2.png) [@countvajhula](https://racket.discourse.group/u/countvajhula)\
**Post date:** [January 16, 2025, 3:58am UTC](https://racket.discourse.group/t/something-like-pipe-forward-in-racket/3492/15 "2025-01-16T03:58:22Z")

</div>

Btw I also noticed that [Rhombus has this operator](https://docs.racket-lang.org/rhombus-reference/ref-function-call.html#%28def._%28%28lib._rhombus%2Fmain..rkt%29._~7c~3e%29%29), in case you want to try that.
