nathaneastwood / poorman

A poor man's dependency free grammar of data manipulation
https://nathaneastwood.github.io/poorman/
Other
338 stars 15 forks source link

[FEAT] a more robust pipe #50

Closed moodymudskipper closed 3 years ago

moodymudskipper commented 4 years ago

Here's a suggestion, it should be 99% consistent with {magrittr}.

`%>%` <- function(lhs, rhs) {
rhs_call <- insert_dot(substitute(rhs))
eval(rhs_call, envir = list(`.` = lhs), enclos = parent.frame())
}

insert_dot <- function(expr) {
  if(is.symbol(expr) || expr[[1]] == quote(`(`)) {
    # if a symbol or an expression inside parentheses, make it a call with dot arg
    expr <- as.call(c(expr, quote(`.`)))
  } else if(length(expr) ==1) {
    # if a call without arg, give it a dot arg
    expr <- as.call(c(expr[[1]], quote(`.`)))
  } else if (expr[[1]] != quote(`{`) &&
             all(vapply(expr[-1], `!=`, quote(`.`), FUN.VALUE = logical(1))) &&
             all(vapply(expr[-1], `!=`, quote(`!!!.`), FUN.VALUE = logical(1)))) {
    # if a call with args but no dot in arg, insert one first
    expr <- as.call(c(expr[[1]], quote(`.`), as.list(expr[-1])))
  }
  expr
}

cars %>% head
#>   speed dist
#> 1     4    2
#> 2     4   10
#> 3     7    4
#> 4     7   22
#> 5     8   16
#> 6     9   10
cars %>% head(.,2)
#>   speed dist
#> 1     4    2
#> 2     4   10
2 %>% head(cars, .)
#>   speed dist
#> 1     4    2
#> 2     4   10
cars %>% {1}
#> [1] 1

Created on 2020-09-23 by the reprex package (v0.3.0)

nathaneastwood commented 4 years ago

It's beautiful! I will run this against the tests - unless you fancy submitting a PR? Hopefully my new GitHub Actions should run the PR against master... fingers crossed

nathaneastwood commented 3 years ago

Hmm...there are definitely problems with this that I'll have to look into sadly.