[Rd] all.equal() applied to function closures -- now committed
> 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
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
> 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
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
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
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
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
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
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
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
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
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