In some computing subcultures, the term “grapes” refers to the percent sign, which R uses to name binary operators such as %*%
. Here, grapes
is an R package that turns arbitrary functions into binary operators. As with the magrittr pipe, this allows you to avoid cumbersome parentheses in your code.
library(grapes)
grow(rbind, c, from = "base") # Use `from` to specify a package or environment to search.
bunch()
## [1] "%c%" "%rbind%"
nrow(sleep)
## [1] 20
longer = sleep %rbind% sleep %rbind% sleep
nrow(longer)
## [1] 60
1 %rbind% 2 %c% 3
## [1] 1 2 3
In your workspace, you can define your own functions for your operators. That way, there is no need to set the from
argument to tell grow()
where to look.
myop <- function(x, y){
1/x + 1/y
}
grow(myop)
2 %myop% 3
## [1] 0.8333333
Use bunch()
and functions()
to list the available operators and non-operator functions.
bunch()
## [1] "%c%" "%myop%" "%rbind%"
functions()
## [1] "myop"
Operators are left-associative!
2 %myop% 3 %myop% 4
## [1] 1.45
(2 %myop% 3) %myop% 4
## [1] 1.45
2 %myop% (3 %myop% 4)
## [1] 2.214286
You can even turn all available functions from a package or environment into operators. But be warned: there is no guarantee that these operators will actually work.
functions("knitr")
## Loading required package: knitr
## [1] "Sweave2knitr" "all_labels" "all_rcpp_labels"
## [4] "asis_output" "clean_cache" "combine_words"
## [7] "current_input" "dep_auto" "dep_prev"
## [10] "engine_output" "extract_raw_output" "fig_chunk"
## [13] "fig_path" "hook_ffmpeg_html" "hook_movecode"
## [16] "hook_optipng" "hook_pdfcrop" "hook_plot_asciidoc"
## [19] "hook_plot_custom" "hook_plot_html" "hook_plot_md"
## [22] "hook_plot_rst" "hook_plot_tex" "hook_plot_textile"
## [25] "hook_purl" "hook_r2swf" "hook_scianimator"
## [28] "image_uri" "imgur_upload" "include_app"
## [31] "include_graphics" "include_url" "inline_expr"
## [34] "kable" "knit" "knit2html"
## [37] "knit2pdf" "knit2wp" "knit_child"
## [40] "knit_exit" "knit_expand" "knit_filter"
## [43] "knit_global" "knit_meta" "knit_meta_add"
## [46] "knit_params" "knit_params_yaml" "knit_print"
## [49] "knit_rd" "knit_rd_all" "knit_watch"
## [52] "load_cache" "normal_print" "pandoc"
## [55] "pat_asciidoc" "pat_brew" "pat_html"
## [58] "pat_md" "pat_rnw" "pat_rst"
## [61] "pat_tex" "pat_textile" "plot_crop"
## [64] "purl" "raw_output" "read_chunk"
## [67] "read_demo" "read_rforge" "render_asciidoc"
## [70] "render_html" "render_jekyll" "render_latex"
## [73] "render_listings" "render_markdown" "render_rst"
## [76] "render_sweave" "render_textile" "restore_raw_output"
## [79] "rocco" "rst2pdf" "set_alias"
## [82] "set_header" "set_parent" "spin"
## [85] "spin_child" "stitch" "stitch_rhtml"
## [88] "stitch_rmd" "wrap_rmd" "write_bib"
bunch("knitr")
## character(0)
grow(from = "knitr")
bunch()
## [1] "%Sweave2knitr%" "%all_labels%" "%all_rcpp_labels%"
## [4] "%asis_output%" "%c%" "%clean_cache%"
## [7] "%combine_words%" "%current_input%" "%dep_auto%"
## [10] "%dep_prev%" "%engine_output%" "%extract_raw_output%"
## [13] "%fig_chunk%" "%fig_path%" "%hook_ffmpeg_html%"
## [16] "%hook_movecode%" "%hook_optipng%" "%hook_pdfcrop%"
## [19] "%hook_plot_asciidoc%" "%hook_plot_custom%" "%hook_plot_html%"
## [22] "%hook_plot_md%" "%hook_plot_rst%" "%hook_plot_tex%"
## [25] "%hook_plot_textile%" "%hook_purl%" "%hook_r2swf%"
## [28] "%hook_scianimator%" "%image_uri%" "%imgur_upload%"
## [31] "%include_app%" "%include_graphics%" "%include_url%"
## [34] "%inline_expr%" "%kable%" "%knit%"
## [37] "%knit2html%" "%knit2pdf%" "%knit2wp%"
## [40] "%knit_child%" "%knit_exit%" "%knit_expand%"
## [43] "%knit_filter%" "%knit_global%" "%knit_meta%"
## [46] "%knit_meta_add%" "%knit_params%" "%knit_params_yaml%"
## [49] "%knit_print%" "%knit_rd%" "%knit_rd_all%"
## [52] "%knit_watch%" "%load_cache%" "%myop%"
## [55] "%normal_print%" "%pandoc%" "%pat_asciidoc%"
## [58] "%pat_brew%" "%pat_html%" "%pat_md%"
## [61] "%pat_rnw%" "%pat_rst%" "%pat_tex%"
## [64] "%pat_textile%" "%plot_crop%" "%purl%"
## [67] "%raw_output%" "%rbind%" "%read_chunk%"
## [70] "%read_demo%" "%read_rforge%" "%render_asciidoc%"
## [73] "%render_html%" "%render_jekyll%" "%render_latex%"
## [76] "%render_listings%" "%render_markdown%" "%render_rst%"
## [79] "%render_sweave%" "%render_textile%" "%restore_raw_output%"
## [82] "%rocco%" "%rst2pdf%" "%set_alias%"
## [85] "%set_header%" "%set_parent%" "%spin%"
## [88] "%spin_child%" "%stitch%" "%stitch_rhtml%"
## [91] "%stitch_rmd%" "%wrap_rmd%" "%write_bib%"
`%purl%`
## function (..., documentation = 1L)
## {
## doc = opts_knit$get("documentation")
## on.exit(opts_knit$set(documentation = doc))
## opts_knit$set(documentation = documentation)
## knit(..., tangle = TRUE)
## }
## <environment: namespace:knitr>
Advanced users can supply environments to the from
and to
arguments. This affords more control over where the functions come from and where the operators get assigned.
to_env = new.env()
from_env = new.env()
from_env$nextop = function(a, b, extra = 3){
sqrt(a^2 + b^2) + extra
}
assign_operator = function(){
grow(nextop, from = from_env, to = to_env)
}
assign_operator()
# 1 %nextop% 2 # throws an error since %nextop% is not defined in your workspace
eval(parse(text = "1 %nextop% 2"), envir = to_env)
## [1] 5.236068
bunch(from_env)
## character(0)
functions(from_env)
## [1] "nextop"
bunch(to_env)
## [1] "%nextop%"
functions(to_env)
## character(0)