Functional pipe operators inspired by the F# and OCaml |>
pipe operator for Clojure.
Also similar to Elixir's and R's pipe operator |>
.
Add the following dependency to your project.clj
:
[com.xadecimal/fpipes "1.0.0"]
Add the following dependency to your deps.edn
:
{:deps {com.xadecimal/fpipes {:mvn/version "1.0.0"}}}
You can use |>
to pipe into the last argument, |<
to pipe into the first and |_
to pipe arbitrarily everywhere you put a _
.
They work like clojure.core/partial
, as they are inspired by OCaml's and F#'s pipe operator.
You want to use them inside the thread-first ->
macro as follows:
(-> [1 2 3]
(|> map (fn [x] (+ x 1)))
(|> reduce (fn [x y] (+ x y)) 0))
;; => 9
(-> [1 2 3]
(|> map (fn [x] (+ x 1))) ;; Pipe into last
(|> reduce (fn [x y] (+ x y)) 0)
(|< str " is the result") ;; Pipe into first
(|_ str "Here " _ " too") ;; Pipe into the _
(|> str))
;; => "Here 9 is the result too"
For |_ you can pick multiple places to pipe into:
(-> [1 2 3]
(|> map (fn [x] (+ x 1)))
(|> reduce (fn [x y] (+ x y)) 0)
(|_ str _ " is the result. I said, " _ " is the result.")) ;; Pipe into all the _
;; => "9 is the result. I said, 9 is the result."
Standard Clojure Threading
(-> "a,b,c"
(str/split #",")
(->> (mapv str/upper-case)
(str/join ";"))
println)
FPipes <-- This library
(-> "a,b,c"
(|< str/split #",")
(|> mapv str/upper-case)
(|> str/join ";")
(|> println))
OCaml
"a,b,c"
|> String.split_on_char ','
|> List.map String.uppercase_ascii
|> String.concat ";"
|> print_string
Elixir
"a,b,c"
|> String.split(",")
|> Enum.map(&String.upcase/1)
|> Enum.join(";")
|> IO.puts
I suggest you refer to all three pipes, and you also need to refer to _
in order to use |_
. In theory, it'll work without when inline, but when used as a function you'll have to have required _
for it to work.
(ns your-ns
(:require [com.xadecimal.fpipes :refer [|> |< |_ _]]))
|>
, |<
, and |_
are functions of the form: (fn [x f & more] (f more... x))
. As you can see, they take a data/coll x
as their first argument and a function as the second argument with possibly more argument, and will call that function with x
as the last argument, or the first or where _
shows up depending which one you use.
Finally, an :inline
form is given to all of them, which does the same as a macro so that there is no additional overhead to using them.
I can't think why you'd use them outside of ->
, so they'd probably always get inlined, but they are functions so you can pass them as arguments to other functions.