[Rd] suggestion: "." in [lsv]apply()

Voeten, C.C. c@c@voeten @end|ng |rom hum@|e|denun|v@n|
Thu Apr 16 19:10:49 CEST 2020


Such a helper already exists in magrittr, which allows you to compose anonymous functions like so:

library(magrittr)
sapply(1:10,. %>% add(4))

That said, I'm all for this being able to be shortened to sapply(1:10,add(.)), but that would require language support, as Serguei asks for. Languages such as Perl already have a similar construct (I'm thinking of Perl 5's $_). It would be nice if R would have such a feature as well. ". %>%" is still quite a mouthful---especially since percentage signs are quite visually salient, so they give the appearance of clutter while the whole construct seems intended to *simplify* such expressions and draw attention to the operation rather than the boilerplate.

Best,
Cesko

> -----Original Message-----
> From: R-devel <r-devel-bounces using r-project.org> On Behalf Of Henrik
> Bengtsson
> Sent: Thursday, April 16, 2020 6:50 PM
> To: Michael Mahoney <mike.mahoney.218 using gmail.com>
> Cc: R-devel <r-devel using r-project.org>
> Subject: Re: [Rd] suggestion: "." in [lsv]apply()
> 
> I'm sure this exists elsewhere, but, as a trade-off, could you achieve
> what you want with a separate helper function F(expr) that constructs
> the function you want to pass to [lsv]apply()?  Something that would
> allow you to write:
> 
> sapply(split(mtcars, mtcars$cyl), F(summary(lm(mpg ~ wt,.))$r.squared))
> 
> Such an F() function would apply elsewhere too.
> 
> /Henrik
> 
> On Thu, Apr 16, 2020 at 9:30 AM Michael Mahoney
> <mike.mahoney.218 using gmail.com> wrote:
> >
> > This syntax is already implemented in the {purrr} package, more or
> > less -- you need to add a tilde before your function call for it to
> > work exactly as written:
> >
> > purrr::map_dbl(split(mtcars, mtcars$cyl), ~ summary(lm(wt ~ mpg,
> .))$r.squared)
> >
> > is equivalent to
> >
> > sapply(split(mtcars, mtcars$cyl), function(d) summary(lm(mpg ~ wt,
> > d))$r.squared)
> >
> > Seems like using this package is probably an easier solution for this
> > wish than adding a reserved variable and adding additional syntax to
> > the apply family as a whole.
> >
> > Thanks,
> >
> > -Mike
> >
> > > From: Sokol Serguei <sokol using insa-toulouse.fr>
> > > Date: Thu, Apr 16, 2020 at 12:03 PM
> > > Subject: Re: [Rd] suggestion: "." in [lsv]apply()
> > > To: William Dunlap <wdunlap using tibco.com>
> > > Cc: r-devel <r-devel using r-project.org>
> > >
> > >
> > > Thanks Bill,
> > >
> > > Clearly, my first proposition for wsapply() is quick and dirty one.
> > > However, if "." becomes a reserved variable with this new syntax,
> > > wsapply() can be fixed (at least for your example and alike) as:
> > >
> > > wsapply=function(l, fun, ...) {
> > >      .=substitute(fun)
> > >      if (is.name(.) || is.call(.) && .[[1]]==as.name("function")) {
> > >          sapply(l, fun, ...)
> > >      } else {
> > >          sapply(l, function(d) eval(., list(.=d)), ...)
> > >      }
> > > }
> > >
> > > Will it do the job?
> > >
> > > Best,
> > > Serguei.
> > >
> > > Le 16/04/2020 à 17:07, William Dunlap a écrit :
> > > > Passing in a function passes not only an argument list but also an
> > > > environment from which to get free variables. Since your function
> > > > doesn't pay attention to the environment you get things like the
> > > > following.
> > > >
> > > > > wsapply(list(1,2:3), paste(., ":", deparse(s)))
> > > > [[1]]
> > > > [1] "1 : paste(., \":\", deparse(s))"
> > > >
> > > > [[2]]
> > > > [1] "2 : paste(., \":\", deparse(s))" "3 : paste(., \":\", deparse(s))"
> > > >
> > > > Bill Dunlap
> > > > TIBCO Software
> > > > wdunlap tibco.com <http://tibco.com>
> > > >
> > > >
> > > > On Thu, Apr 16, 2020 at 7:25 AM Sokol Serguei <sokol using insa-toulouse.fr
> > > > <mailto:sokol using insa-toulouse.fr>> wrote:
> > > >
> > > >     Hi,
> > > >
> > > >     I would like to make a suggestion for a small syntactic
> > > >     modification of
> > > >     FUN argument in the family of functions [lsv]apply(). The idea is to
> > > >     allow one-liner expressions without typing "function(item) {...}" to
> > > >     surround them. The argument to the anonymous function is simply
> > > >     referred
> > > >     as ".". Let take an example. With this new feature, the following call
> > > >
> > > >     sapply(split(mtcars, mtcars$cyl), function(d) summary(lm(mpg ~ wt,
> > > >     d))$r.squared)
> > > >     #        4         6         8
> > > >     #0.5086326 0.4645102 0.4229655
> > > >
> > > >
> > > >     could be rewritten as
> > > >
> > > >     sapply(split(mtcars, mtcars$cyl), summary(lm(mpg ~ wt,
> .))$r.squared)
> > > >
> > > >     "Not a big saving in typing" you can say but multiplied by the
> > > >     number of
> > > >     [lsv]apply usage and a neater look, I think, the idea merits to be
> > > >     considered.
> > > >     To illustrate a possible implementation, I propose a wrapper
> > > >     example for
> > > >     sapply():
> > > >
> > > >     wsapply=function(l, fun, ...) {
> > > >          s=substitute(fun)
> > > >          if (is.name <http://is.name>(s) || is.call(s) &&
> > > >     s[[1]]==as.name <http://as.name>("function")) {
> > > >              sapply(l, fun, ...) # legacy call
> > > >          } else {
> > > >              sapply(l, function(d) eval(s, list(.=d)), ...)
> > > >          }
> > > >     }
> > > >
> > > >     Now, we can do:
> > > >
> > > >     wsapply(split(mtcars, mtcars$cyl), summary(lm(mpg ~ wt,
> .))$r.squared)
> > > >
> > > >     or, traditional way:
> > > >
> > > >     wsapply(split(mtcars, mtcars$cyl), function(d) summary(lm(mpg ~ wt,
> > > >     d))$r.squared)
> > > >
> > > >     the both work.
> > > >
> > > >     How do you feel about that?
> > > >
> > > >     Best,
> > > >     Serguei.
> > > >
> > > >     ______________________________________________
> > > >     R-devel using r-project.org <mailto:R-devel using r-project.org> mailing list
> > > >     https://stat.ethz.ch/mailman/listinfo/r-devel
> > > >
> > >
> > >
> > >         [[alternative HTML version deleted]]
> > >
> > > ______________________________________________
> > > R-devel using r-project.org mailing list
> > > https://stat.ethz.ch/mailman/listinfo/r-devel
> >
> > ______________________________________________
> > R-devel using r-project.org mailing list
> > https://stat.ethz.ch/mailman/listinfo/r-devel
> 
> ______________________________________________
> R-devel using r-project.org mailing list
> https://stat.ethz.ch/mailman/listinfo/r-devel


More information about the R-devel mailing list