Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Julia: Piping operator |> with more than one argument

Tags:

julia

I am attempting to pass multiple arguments to the built in piping operator in Julia |>.

I would like something that works like this:

join([randstring() for i in 1:100], " ")

However, using the piping operator, I get an error instead:

[randstring() for i in 1:100] |> join(" ")

I am pretty sure this is a feature of multiple dispatch with join having its own method with delim in the join(strings, delim, [last]) method being defined as delim="" when omitted.

Am I understanding this correctly? Is there a work around?

For what is is worth the majority of my uses of piping end up taking more than one argument. For example:

[randstring() for i in 1:100] |> join(" ") |> replace("|", " ")
like image 268
Francis Smart Avatar asked May 12 '17 18:05

Francis Smart


2 Answers

The piping operator doesn't do anything magical. It simply takes values on the left and applies them to functions on the right. As you've found, join(" ") does not return a function. In general, partial applications of functions in Julia don't return functions — it'll either mean something different (via multiple dispatch) or it'll be an error.

There are a few options that allow you to support this:

  • Explicitly create anonymous functions:

    [randstring() for i in 1:100] |> x->join(x, " ") |> x->replace(x, "|", " ")
    
  • Use macros to enable the kind of special magic you're looking for. There are some packages that support this kind of thing.

like image 168
mbauman Avatar answered Oct 17 '22 00:10

mbauman


Metaprogramming to the rescue!

We'll use a simple macro to allow piping to multi-input functions.

    using Pipe, Random
    @pipe [randstring() for i in 1:100] |> join(_, " ")

So after calling the Pipe package all we're doing is

  1. using the @pipe macro

  2. designating where where to pipe to with the underscore ("_") [if the function only takes one input we don't need to bother with the underscore: e.g.

     @pipe 2 |> +(3,_) |> *(_,4) |> println   
    

will print "20"]

See here or here for more formal documentation of the Pipe package (not that there's much to document :).

like image 5
Ethan S-L Avatar answered Oct 16 '22 23:10

Ethan S-L