Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

map, reduce with `|>` in julia

Tags:

julia

In R, with dyplr you have the %>% operator which allows you to pipe the output of a function to a new function, removing the need to store intermediate values. In julia you can achieve something very similar by using the |> operator.

Example usage

2 |> log |> sqrt 

To me this reads a lot nicer than sqrt(log(2)). Especially when the chain becomes very long. I would like to use this syntax but also for map,reduce-type functions in Julia.

Setup

from = "abcdefghijklmnopqrstuvwxyz"
to   = "cdefghijklmnopqrstuvwxyzab"
trans = "g fmnc wms bgblr rpylqjyrc gr zw fylb <>"
d = {from[i] => to[i] for i = 1:26}
d[' '] = ' '

What works

map(x -> d[x], filter(x -> isalpha(x) || isspace(x), trans))

This works, but it doesn't read as well as I would like it to. An alternative would be to store intermediate results into variables, but this also seems verbose:

res1 = filter(x -> isalpha(x) || isspace(x), trans)
map(x -> d[x], res1)

What I would prefer

The R syntax would be something similar to this:

trans |> 
  filter(x -> isalpha(x) || isspace(x)) |> 
  map(x -> d[x])

This will not work because in Julia the mapping/filter function goes before the iterable. R would solve this by giving you an infix . that you can use, in which case the syntax would look a bit more like:

trans |> 
  filter(x -> isalpha(x) || isspace(x), .) |> 
  map(x -> d[x], .)

Is something like this possible in Julia? The |> operator has the potential to clean up long chains of code into neat pipes of operations. A perhaps more Julia-thonic way of a approaching the problem would also be considered an answer to this question.

like image 732
cantdutchthis Avatar asked Apr 08 '15 21:04

cantdutchthis


3 Answers

Not exactly sure what you're looking for, but:

SPOILER ALERT 8-)

julia> trans |> 
         t -> filter(x -> isalpha(x) || isspace(x), t) |> 
         f -> map(x -> d[x],f)
"i hope you didnt translate it by hand "
like image 99
rickhg12hs Avatar answered Jan 04 '23 18:01

rickhg12hs


You can also use the @as macro from the Lazy package to get a little closer to your preferred form:

julia> using Lazy

julia> @as _ trans begin
         filter(x -> isalpha(x) || isspace(x), _)
         map(x -> d[x], _)
       end
"i hope you didnt translate it by hand "
like image 31
mbauman Avatar answered Jan 04 '23 17:01

mbauman


You can you the Pipe.jl package to do it like this:

@pipe trans |> filter(x -> isalpha(x) || isspace(x), _) |> map(x -> d[x], _)

Or

@pipe ( trans 
     |> filter(x -> isalpha(x) || isspace(x), _) 
     |> map(x -> d[x], _)
)

The brackets around the arguments to the macro are needed if it goes onto multiple lines.

NB: I am the creator and maintainer of Pipe.jl

like image 44
Lyndon White Avatar answered Jan 04 '23 19:01

Lyndon White