Pipe operator in Elixir is great, you can compose your functions naturally. However, there are times when you want to pipe the input to the second argument. How would you do that?
Desugar
iex> sum_number = fn x, y -> x - y end
iex> sum_number.(20,10)
10
iex> 10 |> sum_number.(20)
-10
# Welp, this doesn't work as intended obviously
Initially, I thought I could curry the sum_number
and 10
will be applied to the curried sum_number
. Here is the desugared version of what actually happens when you do 10 |> sum_number.(20)
.
iex> 10 |> sum_number.(20)
# sum_number(10, y) -> sum_number(10,20) -> -10
# Pipe always pipes the input to the first argument
***My initial thought is (wrong),
# sum_number(20, y) -> sum_number(20,10) -> 10
Obviously, you can solve this with
iex> 20 |> sum_number.(10)
10
# sum_number(20, y) -> sum_number(20,10) -> 10
but my point is that there are certain times that you need behavior like in (***) i.e. you want the input (the left hand side of |>
) to be piped to the second argument.
Solution
In Haskell, I can do something like this because Haskell has currying support. Elixir does not have built-in support for currying.
main = do
print $ (flip sumNumber 10) 20
-- flip will flip the arguments position, x y -> y x
-- (flip sumNumber 10) gives out a function that takes another input
sumNumber :: Int -> Int -> Int
sumNumber x y = x - y
In Elixir, I could make use of &
operator
iex> 10 |> (&sum_number.(20, &1)).()
10
My example above is a little contrived. Here is another one,
struct
|> transform_struct # this returns another struct
|> (&extract_something_from_struct(keyword, &1)).()
|> IO.puts # print extracted value
where extract_something_from_struct
can be something like
def extract_something_from_struct(keyword, struct) do
# retrieve keyword value from struct
end