Open vspinu opened 5 years ago
That looks like a useful function, but is there an equivalent to ...
where it's used in other languages to handle variable arguments which pass through? I can imagine this potentially causing a less defined set of behaviours to capture.
For example, if there's a function foo <- function(x = 1, y = 2, ...) {<function contents>}
would z %>>% foo(a)
mean foo(a, z)
or foo(a, y=2, z)
where y=2 comes from missing argument taking default?
That's ok. Just like with R where %>%
manipulates the code, ->>
in lisps is a macro which transforms the code at compile time. So z %>>% foo(a)
should be exactly equivalent to foo(a,z)
.
There is no ability to pass a named argument. Would be great if y = z %>% foo(a)
would be transformed into foo(a, y=z)
. Not sure if it's possible though.
You can pass to named arguments in positions other than first already in
%>%
using the .
operator in place of the argument you need to replace
(see the %>%
help for more details).
Very useful when needing to pass to functions in positions other than first argument, pretty much anything before tidyverse approaches became widespread!
You could do :
foo <- function(a=2, b) {
c(a,b)
}
`%>>%` <-
function (lhs, rhs) {
rhs_call <- insert_dot_last(substitute(rhs))
eval(rhs_call, envir = list(. = lhs), enclos = parent.frame())
}
insert_dot_last <-
function(expr, special_cases = TRUE) {
if(is.symbol(expr) || expr[[1]] == quote(`(`)) {
# if a symbol or an expression inside parentheses, make it a call with
# a dot arg
expr <- as.call(c(expr, quote(`.`)))
} else if(length(expr) ==1) {
# if a call without arg, same thing
expr <- as.call(c(expr[[1]], quote(`.`)))
} else if (expr[[1]] != quote(`{`) &&
all(sapply(expr[-1], `!=`, quote(`.`)))) {
# if a call with args but no dot in arg, insert dot in last place
expr <- as.call(c(as.list(expr), quote(`.`)))
}
expr
}
1 %>>% foo(2)
#> [1] 2 1
1 %>>% foo(2, .)
#> [1] 2 1
1 %>>% foo(., 2)
#> [1] 1 2
%>>% is already used by pipeR as the primary pipe operator. Plus as mattmalin stated .
already allows you to sned input wherever you want. I think rather than another operator it's probably better practice to encourage users to explicitly define where their input is being piped when not to the first unnamed argument.
Apologies for necroposting.
Though not as frequently as piping first argument it's often needed to pipe the last argument.
Would you mind adding the
%>>%
operator?>>
because in clojure these operators are->
and->>
respectively. Racket uses f> and l>.