[Rd] all.equal() applied to function closures -- now committed

2020-12-04 Thread Martin Maechler
> Martin Maechler 
> on Thu, 3 Dec 2020 18:29:58 +0100 writes:

> Martin Maechler 
> on Tue, 1 Dec 2020 10:31:36 +0100 writes:

> Bill Dunlap 
> on Mon, 30 Nov 2020 13:41:54 -0800 writes:

>>> To make the comparison more complete,
>>> all.equal.environment could compare the parents of the
>>> target and current environments.  That would have to be
>>> recursive but could stop at the first 'top level
>>> environment' (the global, empty, or a package-related
>>> environment generally) and use identical there.  E.g.,

>>> > f1 <- function(x) (function(){ expx <- exp(x) ; function(y) y + 
expx})()
>>> > all.equal(f1(2), f1(3))
>>> [1] "Environments: Component “expx”: Mean relative difference: 1.718282"
>>> 
>>> [2] "Environments:  Component “x”: Mean relative difference:
>>> 0.5"

>>> This is from the following, where I avoided putting the existing
>>> non-recursive all.equal.environment into the body of this one.

> [[.]]

>> Thank you, Duncan and Bill (and Kevin for bringing up the
>> topic).

>> I agree  all.equal() should work better with functions,

>> and I think probably it would make sense to define  all.equal.function()
>> rather than put this into all.equal.default()

>> However, it's not quite clear if it is always desirable to check the
>> environments as well notably as that *is* done recursively.

> A small  "work in progress" update (because I've been advancing slowly 
only):

> I'm currently testing 'make check-all' after

> 1) adding all.equal.function() method,
> 2) not changing  all.equal.environment() yet
> 3) but adapting all.equal.default() to give a deprecating warning
> when called with a function

> all.equal.function <- function(target, current, check.environments = 
TRUE, ...)
> {
[]
> }

> It's amazing that this breaks our own checks in several places,
> which I'm chasing slowly (being busy with teaching related
> duties, etc).
> I did have the correct gut feeling to have 'check.environments'
> being an optional argument, because indeed there are cases (in
> our own regression tests) where we now needed to change the
> checks to use   check.environments=FALSE .

> My plan is to finish the   all.equal.function()  functionality /
> modify "base R" coded (or, for now, rather the testing code)
> where needed, and then *commit* that to R-devel.

I've done that now:

r79555 | maechler | 2020-12-04 12:13:06 +0100 (Fri, 04 Dec 2020) | 1 line
Changed paths:
   M doc/NEWS.Rd
   M src/library/base/R/all.equal.R
   M src/library/base/R/zzz.R
   M src/library/base/man/all.equal.Rd
   M src/library/base/man/dput.Rd
   M src/library/stats/tests/nls.R
   M src/library/stats/tests/nls.Rout.save
   M tests/eval-etc-2.Rout.save
   M tests/eval-etc.Rout.save
   M tests/eval-fns.R
   M tests/reg-tests-1d.R

new all.equal.function() checks environment(.)


Note the seven extra files needed to be changed

  src/library/base/man/dput.Rd
  src/library/stats/tests/nls.{R,Rout.save}
  tests/eval-{etc.Rout.save,fns.Rtests/eval-etc{,-2}.Rout.save}

where in all cases I needed to add an explicit
', check.environments = FALSE' to an existing  stopifnot(all.equal(..))
check.

Consequently, I expect some  "carnage" in checks of existing  CRAN / BioC 
(and github, etc but that does not count) packages.

The NEWS entry (in 'NEW FEATURES') mentions an important case :

• all.equal(f, g) for functions now by default also compares their
  environment(.)s, notably via new all.equal method for class
  function.  Comparison of nls() fits, e.g., may now need
  all.equal(m1, m2, check.environments=FALSE).

So if you are a package maintainer observing that all.equal() --
or its corresponding 'testthat' obfuscation -- signals errors
"suddenly" (and only in R-devel), it's that you need to add
'check.environments=FALSE' there.

The good news is that this works also in existing (and previous)
versions of R :

  > all.equal(lm,lm, check.environments=FALSE)
  [1] TRUE
  > 

thanks to the "..."  _feature_ of typically just silently swallowing
everything that's not understood.  (yes: _feature_ is tongue in cheek).

Martin


> After that we should come back to improve or even re-write
> all.equal.environment()  when needed.

__
R-devel@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel


[Rd] New pipe operator

2020-12-04 Thread Duncan Murdoch

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


Re: [Rd] New pipe operator

2020-12-04 Thread 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 :
>
> 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


Re: [Rd] New pipe operator

2020-12-04 Thread 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.

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 :


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


Re: [Rd] New pipe operator

2020-12-04 Thread Dénes Tóth



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

__
R-devel@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel


Re: [Rd] New pipe operator

2020-12-04 Thread Sebastian Meyer
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 :
>>>
>>> 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


Re: [Rd] New pipe operator

2020-12-04 Thread Deepayan Sarkar
On Fri, Dec 4, 2020 at 7:35 PM Duncan Murdoch  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 :
> >>
> >> 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


Re: [Rd] [External] Re: New pipe operator

2020-12-04 Thread luke-tierney

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

__
R-devel@r-project.org 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 andFax:   319-335-3017
   Actuarial Science
241 Schaeffer Hall  email:   luke-tier...@uiowa.edu
Iowa City, IA 52242 WWW:  http://www.stat.uiowa.edu
__
R-devel@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel


Re: [Rd] New pipe operator

2020-12-04 Thread Duncan Murdoch

On 04/12/2020 12:06 p.m., Deepayan Sarkar wrote:

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


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


Re: [Rd] [External] Re: New pipe operator

2020-12-04 Thread Duncan Murdoch

On 04/12/2020 2:26 p.m., luke-tier...@uiowa.edu 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

__
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


Re: [Rd] [External] Re: New pipe operator

2020-12-04 Thread luke-tierney

On Sat, 5 Dec 2020, Duncan Murdoch wrote:


On 04/12/2020 2:26 p.m., luke-tier...@uiowa.edu 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

__
R-devel@r-project.org 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 andFax:   319-335-3017
   Actuarial Science
241 Schaeffer Hall  email:   luke-tier...@uiowa.edu
Iowa City, IA 52242 WWW:  http://www.stat.uiowa.edu
__
R-devel@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel


Re: [Rd] [External] Re: New pipe operator

2020-12-04 Thread Ivan Krylov
On Fri, 4 Dec 2020 20:11:17 -0600 (CST)
luke-tier...@uiowa.edu 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) `/`

__
R-devel@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel