Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how does |> pipe operator in elixir work?

Tags:

elixir

is this all similar to using | operator on unix? As per the doc it is about passing first argument to the function, so would like to know what is the big deal here about this operator compared to traditional way of passing first argument in any functional language like in Pascal or C.

Also, can we pass variable argument using this way?

like image 238
Amol Pujari Avatar asked Jan 11 '17 07:01

Amol Pujari


People also ask

What does |> mean in Elixir?

This is the pipe operator. From the linked docs: This operator introduces the expression on the left-hand side as the first argument to the function call on the right-hand side. Examples.

What does the Tidyverse pipe operator %>% do?

The %>% pipe is widely used for data manipulations and is automatically loaded with Tidyverse. The pipe operator is used to execute multiple operations that are in sequence requiring the output of the previous operation as their input argument.

What is use of pipe operator command1 command2?

What is the Pipe Operator? The pipe operator is a special operational function available under the magrittr and dplyr package (basically developed under magrittr), which allows us to pass the result of one function/argument to the other one in sequence. It is generally denoted by symbol %>% in R Programming.

What is true about pipe %>% operator in R?

The pipe operator, written as %>% , has been a longstanding feature of the magrittr package for R. It takes the output of one function and passes it into another function as an argument. This allows us to link a sequence of analysis steps.


2 Answers

The main benefit of the pipe operator is that instead of calling multiple functions in a nested fashion

Enum.join(Enum.map(String.split("hello, world!", " "), &String.capitalize/1), " ")

or having many intermediate "throw-away variables"

string = "hello, world!"
words = String.split(string, " ")
capitalized_words = Enum.map(words, &String.capitalize/1)
Enum.join(capitalized_words, " ")

you can use the pipe operator to write

"hello, world!"
|> String.split(" ")
|> Enum.map(&String.capitalize/1)
|> Enum.join

Most notably, arguments are now very close to the function that receives them. Moreover, the order of the function invocations in the code resembles the order of executions - read from top to bottom instead from the inside out. Finally, not having the unnecessary "throw-away variables" reduces noise.

Not only does it make your code easier to read, it also tends to positively influence how you design your APIs. It encourages you to think about your code as a series of transformations on data, which leads to very clean solutions in many cases.

Also, can we pass variable argument using this way?

No, you cannot pass multiple arguments in this way - although you could use a tuple for example, to pass multiple values via a single argument.

like image 139
Patrick Oscity Avatar answered Nov 21 '22 17:11

Patrick Oscity


is this all similar to using | operator on unix?

Not exactly. Consider the following example:

echo 'foo' | echo 'bar'
#⇒ bar

With an Elixir pipe operator, we were to get foo bar string printed out.

If you want the comparison against unix pipe, it’s more like | xargs, save for xargs will append the standard input to the command given (append the output of the previous command, when used after pipe,) while Elixir pipe operator will prepend the output of the previous command.

what is the big deal here about this operator compared to traditional way of passing first argument

Well, it’s a matter of maintaining readable code. Consider the following task: one should receive parameters from the standard input, validate them, possibly coerce them to the respective types and then perform an action, providing these arguments as an input. In Elixir we’d write this using pipe operator:

input
|> validate(ValidatorEngine)
|> coerce(to: [:int, :float])
|> perform

Without this operator, the exactly same code would look like:

perform(coerce(validate(input, ValidatorEngine), to: [:int, :float]))

What is more readable, maintainable and, after all, elegant?

in any functional language like in Pascal or C

Neither Pascal nor C are functional. These languages are imperative. Those two are related as “having fun” compared to “having functions”.

can we pass variable argument using this way?

It’s easy to check in Elixir codebase: Macro.unpipe that unpipes the foo |> bar |> baz notation has no magic inside. Hence, no, one can not just pipe as many arguments as they wanted. Whenever it’s needed, one uses tuples/lists/maps structures to wrap the output of the previous command to the single term.

like image 21
Aleksei Matiushkin Avatar answered Nov 21 '22 17:11

Aleksei Matiushkin