Dear Luke,
In the meantime I checked the R-syntax branch and the docs; they are
very helpful. I would also like to thank you for putting effort into
this feature. Keeping it at the syntax level is also a very smart
decision. However, the current API might not exploit the full power of
the basic idea.
1) Requiring either an anonymous function or a function call, but not
allowing for symbols which point to functions is inconsistent and will
be misleading for non-experts.
foo <- function(x) x
identical(foo, function(x) x)
mtcars |> foo #bang!
mtcars |> function(x) x #fine?
You stated in :
"
Another variation supported by the implementation is that a symbol on
the RHS is interpreted as the name of a function to call with the LHS
as argument:
```r
> quote(x |> f)
f(x)
```
"
So clearly this is not an implementation issue but a design decision.
As a remedy, two different pipe operators could be introduced:
LHS |> RHS -> RHS is treated as a function call
LHS |>> RHS -> RHS is treated as a function
If |>> is used, it would not matter which notation is used for the RHS
expression; the parser would assume it evaluates to a function.
2) Simplified lambda expression:
IMHO in the vast majority of use cases, this is used for single-argument
functions, so parenthesis would not be required. Hence, both forms would
be valid and equivalent:
\x x + 1
\(x) x + 1
3) Function composition:
Allowing for concise composition of functions would be a great feature.
E.g., instead of
foo <- function(x) print(mean(sqrt(x), na.rm = TRUE), digits = 2)
or
foo <- \x {x |> sqrt() |> mean(na.rm = TRUE) |> print(digits = 2)}
one could write
foo <- \x |> sqrt() |> mean(na.rm = TRUE) |> print(digits = 2)
So basically if the lambda argument is followed by a pipe operator, the
pipe chain is transformed to a function body where the first lambda
argument is inserted into the first position of the pipeline.
Best,
Denes
On 12/5/20 7:10 PM, luke-tier...@uiowa.edu wrote:
We went back and forth on this several times. The key advantage of
requiring parentheses is to keep things simple and consistent. Let's
get some experience with that. If experience shows requiring
parentheses creates too many issues then we can add the option of
dropping them later (with special handling of :: and :::). It's easier
to add flexibility and complexity than to restrict it after the fact.
Best,
luke
On Sat, 5 Dec 2020, Hugh Parsonage wrote:
I'm surprised by the aversion to
mtcars |> nrow
over
mtcars |> nrow()
and I think the decision to disallow the former should be
reconsidered. The pipe operator is only going to be used when the rhs
is a function, so there is no ambiguity with omitting the parentheses.
If it's disallowed, it becomes inconsistent with other treatments like
sapply(mtcars, typeof) where sapply(mtcars, typeof()) would just be
noise. I'm not sure why this decision was taken
If the only issue is with the double (and triple) colon operator, then
ideally `mtcars |> base::head` should resolve to `base::head(mtcars)`
-- in other words, demote the precedence of |>
Obviously (looking at the R-Syntax branch) this decision was
considered, put into place, then dropped, but I can't see why
precisely.
Best,
Hugh.
On Sat, 5 Dec 2020 at 04:07, Deepayan Sarkar
<deepayan.sar...@gmail.com> wrote:
On Fri, Dec 4, 2020 at 7:35 PM Duncan Murdoch
<murdoch.dun...@gmail.com> wrote:
On 04/12/2020 8:13 a.m., Hiroaki Yutani wrote:
Error: function '::' not supported in RHS call of a pipe
To me, this error looks much more friendly than magrittr's error.
Some of them got too used to specify functions without (). This
is OK until they use `::`, but when they need to use it, it takes
hours to figure out why
mtcars %>% base::head
#> Error in .::base : unused argument (head)
won't work but
mtcars %>% head
works. I think this is a too harsh lesson for ordinary R users to
learn `::` is a function. I've been wanting for magrittr to drop the
support for a function name without () to avoid this confusion,
so I would very much welcome the new pipe operator's behavior.
Thank you all the developers who implemented this!
I agree, it's an improvement on the corresponding magrittr error.
I think the semantics of not evaluating the RHS, but treating the pipe
as purely syntactical is a good decision.
I'm not sure I like the recommended way to pipe into a particular
argument:
mtcars |> subset(cyl == 4) |> \(d) lm(mpg ~ disp, data = d)
or
mtcars |> subset(cyl == 4) |> function(d) lm(mpg ~ disp, data = d)
both of which are equivalent to
mtcars |> subset(cyl == 4) |> (function(d) lm(mpg ~ disp, data =
d))()
It's tempting to suggest it should allow something like
mtcars |> subset(cyl == 4) |> lm(mpg ~ disp, data = .)
Which is really not that far off from
mtcars |> subset(cyl == 4) |> \(.) lm(mpg ~ disp, data = .)
once you get used to it.
One consequence of the implementation is that it's not clear how
multiple occurrences of the placeholder would be interpreted. With
magrittr,
sort(runif(10)) %>% ecdf(.)(.)
## [1] 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0
This is probably what you would expect, if you expect it to work at
all, and not
ecdf(sort(runif(10)))(sort(runif(10)))
There would be no such ambiguity with anonymous functions
sort(runif(10)) |> \(.) ecdf(.)(.)
-Deepayan
which would be expanded to something equivalent to the other versions:
but that makes it quite a bit more complicated. (Maybe _ or \. should
be used instead of ., since those are not legal variable names.)
I don't think there should be an attempt to copy magrittr's special
casing of how . is used in determining whether to also include the
previous value as first argument.
Duncan Murdoch
Best,
Hiroaki Yutani
2020年12月4日(金) 20:51 Duncan Murdoch <murdoch.dun...@gmail.com>:
Just saw this on the R-devel news:
R now provides a simple native pipe syntax ‘|>’ as well as a
shorthand
notation for creating functions, e.g. ‘\(x) x + 1’ is parsed as
‘function(x) x + 1’. The pipe implementation as a syntax
transformation
was motivated by suggestions from Jim Hester and Lionel Henry. These
features are experimental and may change prior to release.
This is a good addition; by using "|>" instead of "%>%" there
should be
a chance to get operator precedence right. That said, the ?Syntax
help
topic hasn't been updated, so I'm not sure where it fits in.
There are some choices that take a little getting used to:
> mtcars |> head
Error: The pipe operator requires a function call or an anonymous
function expression as RHS
(I need to say mtcars |> head() instead.) This sometimes leads to
error
messages that are somewhat confusing:
> mtcars |> magrittr::debug_pipe |> head
Error: function '::' not supported in RHS call of a pipe
but
mtcars |> magrittr::debug_pipe() |> head()
works.
Overall, I think this is a great addition, though it's going to be
disruptive for a while.
Duncan Murdoch
______________________________________________
R-devel@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel
______________________________________________
R-devel@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel
______________________________________________
R-devel@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel
______________________________________________
R-devel@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel
______________________________________________
R-devel@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel
______________________________________________
R-devel@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel