These two operators are built into OCaml.
let ( @@ ) f x = f x;;
This is the application operator. It just applies a value to a function.
let ( |> ) x f = f x;;
This is the reverse application operator. It takes a value then a function, and applies the value to the function.
succ;;
- : int -> int = <fun>
succ is the successor function. It just increments its parameter.
succ 1;;
- : int = 2
What if you wanted to take the successor of 2 * 10;;
succ 2 * 10;;
- : int = 30
Uh oh... that's not right, it's okay though, OCaml just found the successor of 2, then multiplied it by 10: $(2 + 1) \times 10 = 30$.
succ (2 * 10);;
- : int = 21
There, that's better, but there's another way of doing this! We can use the application operator!
succ @@ 2 * 10;;
- : int = 21
It changed the precedence rules! OCaml took the 2 * 10, then took the succ of that. This is helpful if you have a really long thing on the right hand side.
let square x = x * x;;
val square : int -> int = <fun>
Let's say you wanted to take 5, increment it, and square it. Right now, we'd write:
square (succ 5);;
- : int = 36
But we can use the pipeline operator to make our lives easier.
5 |> succ |> square
- : int = 36
We can even apply even more and more! This makes it really nice to read from left to right!
5 |> succ |> square |> square |> succ |> square;;
- : int = 1682209
(for comparison, the same without the |> operator would be this)
square (succ (square (square (succ 5))));;
- : int = 1682209
Look at all those ugly parenthesis!