[R] new syntax: bash-like pipe operator

Rainer M Krug r.m.krug at gmail.com
Wed Mar 30 10:14:06 CEST 2011


-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On 29/03/11 18:00, Gabor Grothendieck wrote:
> On Tue, Mar 29, 2011 at 9:56 AM, Robert Sugar <robert.sugar at ebi.ac.uk> wrote:
>> Dear R Community,
>>
>> One thing that always bugged me about R is the abundance of multi-level nested statements, like:
>>
>> cumsum(ifelse(c(1,diff(v)),1,0))
>>
>> because:
>>
>> a) you have to read them inside out as opposed to left-to-right
>> b) in the console you always have to go back and type the parenthesis if you want to nest your statement
>> I kind of like the UNIX pipe operator as a very good abstraction of a data flow and would fancy to have something like this in R:
>> v %|% diff %|% c(1, value) %|% ifelse(value, 1, 0) %|% cumsum
>> so I went ahead and wrote it:
>>
>> "%|%" <- function(x,y)
>> {
>> # Operator similar to the UNIX pipe operator. Allows to set up a chain of functions
>> # where the result of one function will be the input of the next.
>> #
>> # x: any R statement. will be passed to y as a parameter
>> # y: either a) the name of a single-parameter function or b) a function call, where "value"
>> # will be replaced with the x parameter
>> #
>> # Example use 1: > c(1,2,3) %|% sum
>> #   results in [1] 6
>> # Example use 2: > c(1,2,3) %|% rep(value, 10)
>> #   results in [1] 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3
>>
>>        thecall<-match.call() #get call
>>
>>        #for functions with one parameter call it with x. Example: "c(1,2,3) %|% sum" -> 6
>>        if(is.name(thecall$y) || is.function(thecall$y)) return (y(x))
>>
>>        #instead of value use x
>>        value <- eval(thecall$x)
>>
>>        return(eval(thecall$y)) #evaluate
>> }
>>
>> would be happy to receive some feedback on
>>
>> 1. Would you find this useful?

Yes - I definitaly like it - although I will in programming cases still
use the nested calls, but in an "ad-hoc" analysis situation, this would
be really usefull.

>> 2. Is there any bugs/features that you'd like to mention?

While we are at it:

separate pipes for output and error stream which can be send to
different targets (displs, file, console, ...). But I guess that would
require some major changes.

>> 3. Should I go ahead and make an R package on that?

Yes please - I would use it and give feedback.

> 
> That is interesting although note that a simple way to get that order
> without introducing new features is to use intermediate variables.
> Here we use the variable . in order to save space and use .= to assign
> to it.
> 
> # Example 1 above
> .= c(1, 2, 3); sum(.)
> 
> # Example 2 above
> .= c(1, 2, 3); rep(., 10)
> 
> # example in preamble
> v <- c(1, 2, 3)
> .= diff(v); .= c(1, .); .= ifelse(., 1, 0); cumsum(.)

Definitely true, but not nearly as nice and elegant (for Linux user
eyes) as the | piping operator.

Looking forward to the package,

Rainer

> 
> 


- -- 
Rainer M. Krug, PhD (Conservation Ecology, SUN), MSc (Conservation
Biology, UCT), Dipl. Phys. (Germany)

Centre of Excellence for Invasion Biology
Natural Sciences Building
Office Suite 2039
Stellenbosch University
Main Campus, Merriman Avenue
Stellenbosch
South Africa

Tel:        +33 - (0)9 53 10 27 44
Cell:       +27 - (0)8 39 47 90 42
Fax (SA):   +27 - (0)8 65 16 27 82
Fax (D) :   +49 - (0)3 21 21 25 22 44
Fax (FR):   +33 - (0)9 58 10 27 44
email:      Rainer at krugs.de

Skype:      RMkrug
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.10 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iEYEARECAAYFAk2S5k4ACgkQoYgNqgF2egqaJQCghjFqor1sDCdwwwMXIoLEzUhZ
EZAAnA4Pt0uTCKURUWvclQ2aXXARFK2Y
=+2uT
-----END PGP SIGNATURE-----



More information about the R-help mailing list