Is it possible to pipe to a function of several variables?

In some other languages, like R, some package allows one to insert a call to a function of several variables into a sequence of pipes. This is done by specifying all arguments but one and inserting a . in the place of the unspecified argument. For example:

foo(x, y) = x + y
bar(x, y) = x * y
 x = 1
y = 2
x |> foo(., y) |> bar(4, .)
# 12

Can this be done in Julia or with the help of some Julia package?

You can use Pipe.jl.

2 Likes

I would like julia to have this feature, officially.

using Chain

@chain x begin
  foo(y)
  bar(4, _)
end
6 Likes

Don’t hold your breath but RFC: curry underscore arguments to create anonymous functions by stevengj · Pull Request #24990 · JuliaLang/julia · GitHub is the PR to follow.

2 Likes

Adding another example to the pipeline:

using Underscores
@_ x |> foo(__, y) |> bar(4, __)
12
1 Like

Three packages that do what I asked for! As the French say, this is an embarras de richesse. Can you guys duke it out on which one is the best? Or, more precisely, the advantages and disadvantages of each package.

Which one is the fastest?
Which packages can deal with replacing more than one variable simultaneously?
Anything else?

Thanks a million.

You can read more from the plumbing experts on this thread.

1 Like

To my understanding, one of the major differences between piping packages lies in where exactly they put the result of the previous pipe step.

DataPipes.jl ([ANN] DataPipes.jl): the previous result becomes the last function argument by default. This is ideal for common data processing workflows: think functions like map and filter - that’s where Data in the package name comes from.
Of course, one can manually use the previous result anywhere with __:

@p [(a=1, b=2), (a=3, b=4)] |>
	map(_.a + _.b + 2) |>
	first(__, 1)

Disclaimer: I’m the author of DataPipes.jl

Chain.jl: the previous result becomes the first function argument by default. This is convenient for certain other functions and ecosystems, but requires explicitly writing the placeholder in each step when using common data processing functions.

Underscores.jl: always requires specifying where the previous result goes. This adds some boilerplate for common cases, but makes other more general pipelines cleaner. See discussion later in the [ANN] DataPipes.jl thread.

There are other features and differences as well, most notably with anonymous functions, but I think they are less fundamental. See the DataPipes.jl usage notebook for more advanced examples: ⚡ Pluto.jl ⚡.

2 Likes

You can also just create an anonymous function.

x |> x -> foo(x, y) |> x -> bar(4, x)

Yes, and one can also use partial functions using package PartialFunctions. But the point of packages like Pipes, DataPipes, Chain and Underscores is eliminating these complications.