New pipe operator

classic Classic list List threaded Threaded
78 messages Options
1234
Reply | Threaded
Open this post in threaded view
|

New pipe operator

Duncan Murdoch-2
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

______________________________________________
[hidden email] mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel
Reply | Threaded
Open this post in threaded view
|

Re: New pipe operator

Hiroaki Yutani
>  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!

Best,
Hiroaki Yutani

2020年12月4日(金) 20:51 Duncan Murdoch <[hidden email]>:

>
> 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
>
> ______________________________________________
> [hidden email] mailing list
> https://stat.ethz.ch/mailman/listinfo/r-devel

______________________________________________
[hidden email] mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel
Reply | Threaded
Open this post in threaded view
|

Re: New pipe operator

Duncan Murdoch-2
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 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 <[hidden email]>:
>>
>> 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
>>
>> ______________________________________________
>> [hidden email] mailing list
>> https://stat.ethz.ch/mailman/listinfo/r-devel
>
> ______________________________________________
> [hidden email] mailing list
> https://stat.ethz.ch/mailman/listinfo/r-devel
>

______________________________________________
[hidden email] mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel
Reply | Threaded
Open this post in threaded view
|

Re: New pipe operator

Dénes Tóth-2

On 12/4/20 3:05 PM, Duncan Murdoch wrote:
> ...
>
> It's tempting to suggest it should allow something like
>
>    mtcars |> subset(cyl == 4) |> lm(mpg ~ disp, data = .)
>
> 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 support the idea of using an underscore (_) as the placeholder symbol.
  Syntactic sugars work the the best if 1) they require less keystrokes
and/or 2) are easier to read compared to the "normal" syntax, and 3) can
not lead to unexpected bugs (which is a major problem with the magrittr
pipe). Using '_' fulfills all of these criteria since '_' can not clash
with any variable in the environment.

Denes

______________________________________________
[hidden email] mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel
Reply | Threaded
Open this post in threaded view
|

Re: New pipe operator

Sebastian Meyer-4
In reply to this post by Duncan Murdoch-2
Am 04.12.20 um 15:05 schrieb Duncan Murdoch:

> 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.


Thank you for this example. I agree but think that the new base R pipe
might trigger some initial confusion as well:

    mtcars |> function(x) dim(x)[1L]
    #> [1] 32

    mtcars |> nrow
    #> Error: The pipe operator requires a function call or an anonymous
function expression as RHS

The RHS evaluates to the same thing in both cases (bar attributes and
environments), but only the anonymous variant is supported. I admit that
I haven't used %>% before; maybe the above discrepancy is less
irritating for those who have. The error message is clear though!

That said, I think the code is very readable when piping explicitly into
an anonymous function and I also prefer

    mtcars |> nrow()

over mtcars |> nrow, because we are visibly calling something.

IMO, readability is lost when using the cryptic short-hand notation

    mtcars |> \(x) dim(x)[1L]

which really only saves 7 letters.


> 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 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 guess "_" as a placeholder would be difficult to implement precisely
because it currently is a syntax error.

Best regards,

        Sebastian Meyer


> 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 <[hidden email]>:
>>>
>>> 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
>>>
>>> ______________________________________________
>>> [hidden email] mailing list
>>> https://stat.ethz.ch/mailman/listinfo/r-devel
>>
>> ______________________________________________
>> [hidden email] mailing list
>> https://stat.ethz.ch/mailman/listinfo/r-devel
>>
>
> ______________________________________________
> [hidden email] mailing list
> https://stat.ethz.ch/mailman/listinfo/r-devel

______________________________________________
[hidden email] mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel
Reply | Threaded
Open this post in threaded view
|

Re: New pipe operator

Deepayan Sarkar
In reply to this post by Duncan Murdoch-2
On Fri, Dec 4, 2020 at 7:35 PM Duncan Murdoch <[hidden email]> 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 <[hidden email]>:
> >>
> >> 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
> >>
> >> ______________________________________________
> >> [hidden email] mailing list
> >> https://stat.ethz.ch/mailman/listinfo/r-devel
> >
> > ______________________________________________
> > [hidden email] mailing list
> > https://stat.ethz.ch/mailman/listinfo/r-devel
> >
>
> ______________________________________________
> [hidden email] mailing list
> https://stat.ethz.ch/mailman/listinfo/r-devel

______________________________________________
[hidden email] mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel
Reply | Threaded
Open this post in threaded view
|

Re: [External] Re: New pipe operator

luke-tierney
In reply to this post by Dénes Tóth-2
On Fri, 4 Dec 2020, Dénes Tóth wrote:

>
> On 12/4/20 3:05 PM, Duncan Murdoch wrote:
>> ...
>>
>> It's tempting to suggest it should allow something like
>>
>>    mtcars |> subset(cyl == 4) |> lm(mpg ~ disp, data = .)
>>
>> 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 support the idea of using an underscore (_) as the placeholder symbol.

I strongly oppose adding a placeholder. Allowing for an optional
placeholder significantly complicates both implementing and explaining
the semantics. For a simple syntax transformation to be viable it
would also require some restrictions, such as only allowing a
placeholder as a top level argument and only once. Checking that these
restrictions are met, and accurately signaling when they are not with
reasonable error messages, is essentially an unsolvable problem given
R's semantics.

The case where the LHS is to be passed as something other than the
first argument is unusual. For me, having that case stand out by using
a function expression makes it much easier to see and so makes the
code easier to understand. As a wearer of progressive bifocals
and someone whose screen is not always free of small dust particles,
having to spot the non-standard pipe stages by seeing a placeholder,
especially a . placeholder, is be a bug, not a feature.

Best,

luke

> Syntactic sugars work the the best if 1) they require less keystrokes and/or
> 2) are easier to read compared to the "normal" syntax, and 3) can not lead to
> unexpected bugs (which is a major problem with the magrittr pipe). Using '_'
> fulfills all of these criteria since '_' can not clash with any variable in
> the environment.
>
> Denes
>
> ______________________________________________
> [hidden email] mailing list
> https://stat.ethz.ch/mailman/listinfo/r-devel
>

--
Luke Tierney
Ralph E. Wareham Professor of Mathematical Sciences
University of Iowa                  Phone:             319-335-3386
Department of Statistics and        Fax:               319-335-3017
    Actuarial Science
241 Schaeffer Hall                  email:   [hidden email]
Iowa City, IA 52242                 WWW:  http://www.stat.uiowa.edu
______________________________________________
[hidden email] mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel
Reply | Threaded
Open this post in threaded view
|

Re: New pipe operator

Duncan Murdoch-2
In reply to this post by Deepayan Sarkar
On 04/12/2020 12:06 p.m., Deepayan Sarkar wrote:

> On Fri, Dec 4, 2020 at 7:35 PM Duncan Murdoch <[hidden email]> 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)))

I didn't suggest that.  That would be a bad.  All I suggested was
different sugar to write (function(d) ecdf(d)(d))().

Duncan Murdoch

>
> 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 <[hidden email]>:
>>>>
>>>> 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
>>>>
>>>> ______________________________________________
>>>> [hidden email] mailing list
>>>> https://stat.ethz.ch/mailman/listinfo/r-devel
>>>
>>> ______________________________________________
>>> [hidden email] mailing list
>>> https://stat.ethz.ch/mailman/listinfo/r-devel
>>>
>>
>> ______________________________________________
>> [hidden email] mailing list
>> https://stat.ethz.ch/mailman/listinfo/r-devel

______________________________________________
[hidden email] mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel
Reply | Threaded
Open this post in threaded view
|

Re: [External] Re: New pipe operator

Duncan Murdoch-2
In reply to this post by luke-tierney
On 04/12/2020 2:26 p.m., [hidden email] wrote:

> On Fri, 4 Dec 2020, Dénes Tóth wrote:
>
>>
>> On 12/4/20 3:05 PM, Duncan Murdoch wrote:
>>> ...
>>>
>>> It's tempting to suggest it should allow something like
>>>
>>>     mtcars |> subset(cyl == 4) |> lm(mpg ~ disp, data = .)
>>>
>>> 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 support the idea of using an underscore (_) as the placeholder symbol.
>
> I strongly oppose adding a placeholder. Allowing for an optional
> placeholder significantly complicates both implementing and explaining
> the semantics. For a simple syntax transformation to be viable it
> would also require some restrictions, such as only allowing a
> placeholder as a top level argument and only once. Checking that these
> restrictions are met, and accurately signaling when they are not with
> reasonable error messages, is essentially an unsolvable problem given
> R's semantics.

I don't think you read my suggestion, but that's okay:  you're
maintaining it, not me.

Duncan Murdoch

>
> The case where the LHS is to be passed as something other than the
> first argument is unusual. For me, having that case stand out by using
> a function expression makes it much easier to see and so makes the
> code easier to understand. As a wearer of progressive bifocals
> and someone whose screen is not always free of small dust particles,
> having to spot the non-standard pipe stages by seeing a placeholder,
> especially a . placeholder, is be a bug, not a feature.
>
> Best,
>
> luke
>
>> Syntactic sugars work the the best if 1) they require less keystrokes and/or
>> 2) are easier to read compared to the "normal" syntax, and 3) can not lead to
>> unexpected bugs (which is a major problem with the magrittr pipe). Using '_'
>> fulfills all of these criteria since '_' can not clash with any variable in
>> the environment.
>>
>> Denes
>>
>> ______________________________________________
>> [hidden email] mailing list
>> https://stat.ethz.ch/mailman/listinfo/r-devel
>>
>

______________________________________________
[hidden email] mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel
Reply | Threaded
Open this post in threaded view
|

Re: [External] Re: New pipe operator

luke-tierney
On Sat, 5 Dec 2020, Duncan Murdoch wrote:

> On 04/12/2020 2:26 p.m., [hidden email] wrote:
>> On Fri, 4 Dec 2020, Dénes Tóth wrote:
>>
>>>
>>> On 12/4/20 3:05 PM, Duncan Murdoch wrote:
>>>> ...
>>>>
>>>> It's tempting to suggest it should allow something like
>>>>
>>>>     mtcars |> subset(cyl == 4) |> lm(mpg ~ disp, data = .)
>>>>
>>>> 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 support the idea of using an underscore (_) as the placeholder symbol.
>>
>> I strongly oppose adding a placeholder. Allowing for an optional
>> placeholder significantly complicates both implementing and explaining
>> the semantics. For a simple syntax transformation to be viable it
>> would also require some restrictions, such as only allowing a
>> placeholder as a top level argument and only once. Checking that these
>> restrictions are met, and accurately signaling when they are not with
>> reasonable error messages, is essentially an unsolvable problem given
>> R's semantics.
>
> I don't think you read my suggestion, but that's okay:  you're maintaining
> it, not me.

I thought I did but maybe I missed something. You are right that
supporting a placeholder makes things a lot more complicated. For
being able to easily recognize the non-standard cases _ is better than
. but for me at least not by much.

We did try a number of variations; the code is in the R-syntax branch.
At the root of that branch are two .md files with some notes as of
around useR20. Once things settle down I may update those and look
into turning them into a blog post.

Best,

luke

>
> Duncan Murdoch
>
>>
>> The case where the LHS is to be passed as something other than the
>> first argument is unusual. For me, having that case stand out by using
>> a function expression makes it much easier to see and so makes the
>> code easier to understand. As a wearer of progressive bifocals
>> and someone whose screen is not always free of small dust particles,
>> having to spot the non-standard pipe stages by seeing a placeholder,
>> especially a . placeholder, is be a bug, not a feature.
>>
>> Best,
>>
>> luke
>>
>>> Syntactic sugars work the the best if 1) they require less keystrokes
>>> and/or
>>> 2) are easier to read compared to the "normal" syntax, and 3) can not lead
>>> to
>>> unexpected bugs (which is a major problem with the magrittr pipe). Using
>>> '_'
>>> fulfills all of these criteria since '_' can not clash with any variable
>>> in
>>> the environment.
>>>
>>> Denes
>>>
>>> ______________________________________________
>>> [hidden email] mailing list
>>> https://stat.ethz.ch/mailman/listinfo/r-devel
>>>
>>
>
>

--
Luke Tierney
Ralph E. Wareham Professor of Mathematical Sciences
University of Iowa                  Phone:             319-335-3386
Department of Statistics and        Fax:               319-335-3017
    Actuarial Science
241 Schaeffer Hall                  email:   [hidden email]
Iowa City, IA 52242                 WWW:  http://www.stat.uiowa.edu
______________________________________________
[hidden email] mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel
Reply | Threaded
Open this post in threaded view
|

Re: [External] Re: New pipe operator

R devel mailing list
Luke and others,

Can anyone comment on how this new pipe operator will interoperate with existing pipe methods or packages like the tidyverse that currently do things using them?

What differences might it make for efficiency? For example, making an anonymous function just so you can call another function and pass along the results to somewhere other than the first argument sounds like extra overhead. But the anonymous function does provide some interesting scenarios that allow things like a sort of tee functionality that may print/graph  a mid-stream result as well as pass it along the pipeline or do amusing things like apply multiple steps to the data and perhaps concatenate some of the results in the output. Of course, that can be done now with a non-anonymous function.

Perhaps we should name one version (or the other) a pipette or a pipe dream 😉

The name "pipe" feels better in the new version as "|>" has the UNIX pipe symbol "|" in it.


-----Original Message-----
From: R-devel <[hidden email]> On Behalf Of [hidden email]
Sent: Friday, December 4, 2020 9:11 PM
To: Duncan Murdoch <[hidden email]>
Cc: [hidden email]
Subject: Re: [Rd] [External] Re: New pipe operator

On Sat, 5 Dec 2020, Duncan Murdoch wrote:

> On 04/12/2020 2:26 p.m., [hidden email] wrote:
>> On Fri, 4 Dec 2020, Dénes Tóth wrote:
>>
>>>
>>> On 12/4/20 3:05 PM, Duncan Murdoch wrote:
>>>> ...
>>>>
>>>> It's tempting to suggest it should allow something like
>>>>
>>>>     mtcars |> subset(cyl == 4) |> lm(mpg ~ disp, data = .)
>>>>
>>>> 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 support the idea of using an underscore (_) as the placeholder symbol.
>>
>> I strongly oppose adding a placeholder. Allowing for an optional
>> placeholder significantly complicates both implementing and
>> explaining the semantics. For a simple syntax transformation to be
>> viable it would also require some restrictions, such as only allowing
>> a placeholder as a top level argument and only once. Checking that
>> these restrictions are met, and accurately signaling when they are
>> not with reasonable error messages, is essentially an unsolvable
>> problem given R's semantics.
>
> I don't think you read my suggestion, but that's okay:  you're
> maintaining it, not me.

I thought I did but maybe I missed something. You are right that supporting a placeholder makes things a lot more complicated. For being able to easily recognize the non-standard cases _ is better than . but for me at least not by much.

We did try a number of variations; the code is in the R-syntax branch.
At the root of that branch are two .md files with some notes as of around useR20. Once things settle down I may update those and look into turning them into a blog post.

Best,

luke

>
> Duncan Murdoch
>
>>
>> The case where the LHS is to be passed as something other than the
>> first argument is unusual. For me, having that case stand out by
>> using a function expression makes it much easier to see and so makes
>> the code easier to understand. As a wearer of progressive bifocals
>> and someone whose screen is not always free of small dust particles,
>> having to spot the non-standard pipe stages by seeing a placeholder,
>> especially a . placeholder, is be a bug, not a feature.
>>
>> Best,
>>
>> luke
>>
>>> Syntactic sugars work the the best if 1) they require less
>>> keystrokes and/or
>>> 2) are easier to read compared to the "normal" syntax, and 3) can
>>> not lead to unexpected bugs (which is a major problem with the
>>> magrittr pipe). Using '_'
>>> fulfills all of these criteria since '_' can not clash with any
>>> variable in the environment.
>>>
>>> Denes
>>>
>>> ______________________________________________
>>> [hidden email] mailing list
>>> https://stat.ethz.ch/mailman/listinfo/r-devel
>>>
>>
>
>

--
Luke Tierney
Ralph E. Wareham Professor of Mathematical Sciences
University of Iowa                  Phone:             319-335-3386
Department of Statistics and        Fax:               319-335-3017
    Actuarial Science
241 Schaeffer Hall                  email:   [hidden email]
Iowa City, IA 52242                 WWW:  http://www.stat.uiowa.edu
______________________________________________
[hidden email] mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel


Scanned by McAfee and confirmed virus-free.
Find out more here: https://bit.ly/2zCJMrO

______________________________________________
[hidden email] mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel
Reply | Threaded
Open this post in threaded view
|

Re: [External] Re: New pipe operator

Ivan Krylov
In reply to this post by luke-tierney
On Fri, 4 Dec 2020 20:11:17 -0600 (CST)
[hidden email] wrote:

> We did try a number of variations; the code is in the R-syntax branch.
> At the root of that branch are two .md files with some notes as of
> around useR20.

Thanks for the information!

Can I make a suggestion? If the variation of the pipe that allows
a symbol on the RHS to be interpreted as the name of a function to call
does get chosen, may it also allow fully-qualified symbols?

Index: src/main/gram.y
===================================================================
--- src/main/gram.y     (revision 79567)
+++ src/main/gram.y     (working copy)
@@ -1242,7 +1242,11 @@
     if (GenerateCode) {
        /* allow for symbols or lambda expressions */
        if (TYPEOF(rhs) == SYMSXP ||
-           TYPEOF(rhs) == LANGSXP && CAR(rhs) == R_FunctionSymbol)
+           TYPEOF(rhs) == LANGSXP && (
+               CAR(rhs) == R_FunctionSymbol ||
+               CAR(rhs) == R_DoubleColonSymbol ||
+               CAR(rhs) == R_TripleColonSymbol
+           ))
            return lang2(rhs, lhs);
                   
        if (TYPEOF(rhs) != LANGSXP)

Or is this feature creep?

--
Best regards,
Ivan

P.S. This lambda function is waving at us: \ (O,o) `/`

______________________________________________
[hidden email] mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel
Reply | Threaded
Open this post in threaded view
|

Re: [External] Re: New pipe operator

Duncan Murdoch-2
In reply to this post by luke-tierney
On 04/12/2020 9:11 p.m., [hidden email] wrote:

> On Sat, 5 Dec 2020, Duncan Murdoch wrote:
>
>> On 04/12/2020 2:26 p.m., [hidden email] wrote:
>>> On Fri, 4 Dec 2020, Dénes Tóth wrote:
>>>
>>>>
>>>> On 12/4/20 3:05 PM, Duncan Murdoch wrote:
>>>>> ...
>>>>>
>>>>> It's tempting to suggest it should allow something like
>>>>>
>>>>>      mtcars |> subset(cyl == 4) |> lm(mpg ~ disp, data = .)
>>>>>
>>>>> 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 support the idea of using an underscore (_) as the placeholder symbol.
>>>
>>> I strongly oppose adding a placeholder. Allowing for an optional
>>> placeholder significantly complicates both implementing and explaining
>>> the semantics. For a simple syntax transformation to be viable it
>>> would also require some restrictions, such as only allowing a
>>> placeholder as a top level argument and only once. Checking that these
>>> restrictions are met, and accurately signaling when they are not with
>>> reasonable error messages, is essentially an unsolvable problem given
>>> R's semantics.
>>
>> I don't think you read my suggestion, but that's okay:  you're maintaining
>> it, not me.
>
> I thought I did but maybe I missed something. You are right that
> supporting a placeholder makes things a lot more complicated. For
> being able to easily recognize the non-standard cases _ is better than
> . but for me at least not by much.
>
> We did try a number of variations; the code is in the R-syntax branch.
> At the root of that branch are two .md files with some notes as of
> around useR20. Once things settle down I may update those and look
> into turning them into a blog post.

Thanks for pointing out those documents.

Duncan Murdoch

______________________________________________
[hidden email] mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel
Reply | Threaded
Open this post in threaded view
|

Re: New pipe operator

Hugh Parsonage
In reply to this post by Deepayan Sarkar
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 <[hidden email]> wrote:

>
> On Fri, Dec 4, 2020 at 7:35 PM Duncan Murdoch <[hidden email]> 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 <[hidden email]>:
> > >>
> > >> 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
> > >>
> > >> ______________________________________________
> > >> [hidden email] mailing list
> > >> https://stat.ethz.ch/mailman/listinfo/r-devel
> > >
> > > ______________________________________________
> > > [hidden email] mailing list
> > > https://stat.ethz.ch/mailman/listinfo/r-devel
> > >
> >
> > ______________________________________________
> > [hidden email] mailing list
> > https://stat.ethz.ch/mailman/listinfo/r-devel
>
> ______________________________________________
> [hidden email] mailing list
> https://stat.ethz.ch/mailman/listinfo/r-devel

______________________________________________
[hidden email] mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel
Reply | Threaded
Open this post in threaded view
|

Re: New pipe operator

Gabor Grothendieck
The construct utils::head  is not that common but bare functions are
very common and to make it harder to use the common case so that
the uncommon case is slightly easier is not desirable.

Also it is trivial to write this which does work:

mtcars %>% (utils::head)

On Sat, Dec 5, 2020 at 11:59 AM Hugh Parsonage <[hidden email]> 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 <[hidden email]> wrote:
> >
> > On Fri, Dec 4, 2020 at 7:35 PM Duncan Murdoch <[hidden email]> 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 <[hidden email]>:
> > > >>
> > > >> 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
> > > >>
> > > >> ______________________________________________
> > > >> [hidden email] mailing list
> > > >> https://stat.ethz.ch/mailman/listinfo/r-devel
> > > >
> > > > ______________________________________________
> > > > [hidden email] mailing list
> > > > https://stat.ethz.ch/mailman/listinfo/r-devel
> > > >
> > >
> > > ______________________________________________
> > > [hidden email] mailing list
> > > https://stat.ethz.ch/mailman/listinfo/r-devel
> >
> > ______________________________________________
> > [hidden email] mailing list
> > https://stat.ethz.ch/mailman/listinfo/r-devel
>
> ______________________________________________
> [hidden email] mailing list
> https://stat.ethz.ch/mailman/listinfo/r-devel



--
Statistics & Software Consulting
GKX Group, GKX Associates Inc.
tel: 1-877-GKX-GROUP
email: ggrothendieck at gmail.com

______________________________________________
[hidden email] mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel
Reply | Threaded
Open this post in threaded view
|

Re: [External] Re: New pipe operator

luke-tierney
In reply to this post by Hugh Parsonage
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 <[hidden email]> wrote:
>>
>> On Fri, Dec 4, 2020 at 7:35 PM Duncan Murdoch <[hidden email]> 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 <[hidden email]>:
>>>>>
>>>>> 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
>>>>>
>>>>> ______________________________________________
>>>>> [hidden email] mailing list
>>>>> https://stat.ethz.ch/mailman/listinfo/r-devel
>>>>
>>>> ______________________________________________
>>>> [hidden email] mailing list
>>>> https://stat.ethz.ch/mailman/listinfo/r-devel
>>>>
>>>
>>> ______________________________________________
>>> [hidden email] mailing list
>>> https://stat.ethz.ch/mailman/listinfo/r-devel
>>
>> ______________________________________________
>> [hidden email] mailing list
>> https://stat.ethz.ch/mailman/listinfo/r-devel
>
> ______________________________________________
> [hidden email] mailing list
> https://stat.ethz.ch/mailman/listinfo/r-devel
>

--
Luke Tierney
Ralph E. Wareham Professor of Mathematical Sciences
University of Iowa                  Phone:             319-335-3386
Department of Statistics and        Fax:               319-335-3017
    Actuarial Science
241 Schaeffer Hall                  email:   [hidden email]
Iowa City, IA 52242                 WWW:  http://www.stat.uiowa.edu
______________________________________________
[hidden email] mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel
Reply | Threaded
Open this post in threaded view
|

Re: New pipe operator

John Mount
In reply to this post by Gabor Grothendieck
The :: is a case that we worked to get right with wrapr dot-pipe. I shared notes on this S3/S4 pipe in the R journal https://journal.r-project.org/archive/2018/RJ-2018-042/index.html

library(magrittr)
packageVersion("magrittr")
# [1] ‘2.0.1’
5 %>% base::sin
# Error in .::base : unused argument (sin)

library(wrapr)
5 %.>% base::sin
# [1] -0.9589243


On Dec 5, 2020, at 10:08 AM, Gabor Grothendieck <[hidden email]<mailto:[hidden email]>> wrote:

The construct utils::head  is not that common but bare functions are
very common and to make it harder to use the common case so that
the uncommon case is slightly easier is not desirable.

Also it is trivial to write this which does work:

mtcars %>% (utils::head)

On Sat, Dec 5, 2020 at 11:59 AM Hugh Parsonage <[hidden email]<mailto:[hidden email]>> 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 <[hidden email]<mailto:[hidden email]>> wrote:

On Fri, Dec 4, 2020 at 7:35 PM Duncan Murdoch <[hidden email]<mailto:[hidden email]>> 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 <[hidden email]<mailto:[hidden email]>>:

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

______________________________________________
[hidden email]<mailto:[hidden email]> mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel

______________________________________________
[hidden email]<mailto:[hidden email]> mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel


______________________________________________
[hidden email]<mailto:[hidden email]> mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel

______________________________________________
[hidden email]<mailto:[hidden email]> mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel

______________________________________________
[hidden email]<mailto:[hidden email]> mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel



--
Statistics & Software Consulting
GKX Group, GKX Associates Inc.
tel: 1-877-GKX-GROUP
email: ggrothendieck at gmail.com<http://gmail.com>

______________________________________________
[hidden email]<mailto:[hidden email]> mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel


        [[alternative HTML version deleted]]

______________________________________________
[hidden email] mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel
Reply | Threaded
Open this post in threaded view
|

Re: New pipe operator

aBBy Spurdle, ⍺XY
In reply to this post by Duncan Murdoch-2
> This is a good addition

I can't understand why so many people are calling this a "pipe".
Pipes connect processes, via their I/O streams.
Arguably, a more general interpretation would include sockets and files.

https://en.wikipedia.org/wiki/Pipeline_(Unix)
https://en.wikipedia.org/wiki/Named_pipe
https://en.wikipedia.org/wiki/Anonymous_pipe

As far as I can tell, the magrittr-like operators are functions (not
pipes), with nonstandard syntax.
This is not consistent with R's original design philosophy, building
on C, Lisp and S, along with lots of *important* math and stats.

It's possible that some parties are interested in creating a kind of
"data pipeline".
I'm interested in this myself, and I think we could discuss this more.
But I'm not convinced the magrittr-like operators help to achieve this goal.
Which, in my opinion, would require one to model programs as directed
graphs, along with some degree of asynchronous input.

Presumably, these operators will be added to R anyway, and (almost) no
one will listen to me.

So, I would like to make one suggestion:
Is it possible for these operators to *not* be named:
    The R Pipe
    The S Pipe
    Or anything with a similar meaning.

Maybe tidy pipe, or something else that links it to its proponents?

______________________________________________
[hidden email] mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel
Reply | Threaded
Open this post in threaded view
|

Re: New pipe operator

Gregory Warnes-2
If we’re being mathematically pedantic, the “pipe” operator is actually
function composition.

That being said, pipes are a simple and well-known idiom. While being less
than mathematically exact, it seems a reasonable   label for the (very
useful) behavior.

On Sat, Dec 5, 2020 at 9:43 PM Abby Spurdle <[hidden email]> wrote:

> > This is a good addition
>
> I can't understand why so many people are calling this a "pipe".
> Pipes connect processes, via their I/O streams.
> Arguably, a more general interpretation would include sockets and files.
>
> https://en.wikipedia.org/wiki/Pipeline_(Unix)
> https://en.wikipedia.org/wiki/Named_pipe
> https://en.wikipedia.org/wiki/Anonymous_pipe
>
> As far as I can tell, the magrittr-like operators are functions (not
> pipes), with nonstandard syntax.
> This is not consistent with R's original design philosophy, building
> on C, Lisp and S, along with lots of *important* math and stats.
>
> It's possible that some parties are interested in creating a kind of
> "data pipeline".
> I'm interested in this myself, and I think we could discuss this more.
> But I'm not convinced the magrittr-like operators help to achieve this
> goal.
> Which, in my opinion, would require one to model programs as directed
> graphs, along with some degree of asynchronous input.
>
> Presumably, these operators will be added to R anyway, and (almost) no
> one will listen to me.
>
> So, I would like to make one suggestion:
> Is it possible for these operators to *not* be named:
>     The R Pipe
>     The S Pipe
>     Or anything with a similar meaning.
>
> Maybe tidy pipe, or something else that links it to its proponents?
>
> ______________________________________________
> [hidden email] mailing list
> https://stat.ethz.ch/mailman/listinfo/r-devel
>
--
"Whereas true religion and good morals are the only solid foundations of
public liberty and happiness . . . it is hereby earnestly recommended to
the several States to take the most effectual measures for the
encouragement thereof." Continental Congress, 1778

        [[alternative HTML version deleted]]

______________________________________________
[hidden email] mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel
Reply | Threaded
Open this post in threaded view
|

Re: New pipe operator

Hiroaki Yutani
It is common practice to call |> as pipe (or pipeline operator) among
many languages
including ones that recently introduced it as an experimental feature.
Pipeline is a
common feature for functional programming, not just for "data pipeline."

    F#: https://docs.microsoft.com/en-us/dotnet/fsharp/language-reference/symbol-and-operator-reference/
    Elixir: https://hexdocs.pm/elixir/operators.html#general-operators
    Typescript:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Pipeline_operator
    Ruby: https://bugs.ruby-lang.org/issues/15799

(This blog post about the history of pipe operator might be
interesting: https://mamememo.blogspot.com/2019/06/a-brief-history-of-pipeline-operator.html
)

I agree this is a bit confusing for those who are familiar with other
"pipe" concepts,
but there's no other appropriate term to call |>.

2020年12月6日(日) 12:22 Gregory Warnes <[hidden email]>:

>
> If we’re being mathematically pedantic, the “pipe” operator is actually
> function composition.
>
> That being said, pipes are a simple and well-known idiom. While being less
> than mathematically exact, it seems a reasonable   label for the (very
> useful) behavior.
>
> On Sat, Dec 5, 2020 at 9:43 PM Abby Spurdle <[hidden email]> wrote:
>
> > > This is a good addition
> >
> > I can't understand why so many people are calling this a "pipe".
> > Pipes connect processes, via their I/O streams.
> > Arguably, a more general interpretation would include sockets and files.
> >
> > https://en.wikipedia.org/wiki/Pipeline_(Unix)
> > https://en.wikipedia.org/wiki/Named_pipe
> > https://en.wikipedia.org/wiki/Anonymous_pipe
> >
> > As far as I can tell, the magrittr-like operators are functions (not
> > pipes), with nonstandard syntax.
> > This is not consistent with R's original design philosophy, building
> > on C, Lisp and S, along with lots of *important* math and stats.
> >
> > It's possible that some parties are interested in creating a kind of
> > "data pipeline".
> > I'm interested in this myself, and I think we could discuss this more.
> > But I'm not convinced the magrittr-like operators help to achieve this
> > goal.
> > Which, in my opinion, would require one to model programs as directed
> > graphs, along with some degree of asynchronous input.
> >
> > Presumably, these operators will be added to R anyway, and (almost) no
> > one will listen to me.
> >
> > So, I would like to make one suggestion:
> > Is it possible for these operators to *not* be named:
> >     The R Pipe
> >     The S Pipe
> >     Or anything with a similar meaning.
> >
> > Maybe tidy pipe, or something else that links it to its proponents?
> >
> > ______________________________________________
> > [hidden email] mailing list
> > https://stat.ethz.ch/mailman/listinfo/r-devel
> >
> --
> "Whereas true religion and good morals are the only solid foundations of
> public liberty and happiness . . . it is hereby earnestly recommended to
> the several States to take the most effectual measures for the
> encouragement thereof." Continental Congress, 1778
>
>         [[alternative HTML version deleted]]
>
> ______________________________________________
> [hidden email] mailing list
> https://stat.ethz.ch/mailman/listinfo/r-devel

______________________________________________
[hidden email] mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel
1234