Thanks Simon, Now, I see better your argument. Le 16/04/2020 ? 22:48, Simon Urbanek a ?crit?:> ... I'm not arguing against the principle, I'm arguing about your > particular proposal as it is inconsistent and not general.This sounds promising for me. May be in a (new?) future, R core will come with a correct proposal for this principle? Meanwhile, to avoid substitute(), I'll look on the side of formula syntax deviation as your example x ~> i + x suggested. Best, Serguei.> Personally, I find the current syntax much clearer and readable > (defining anything by convention like . being the function variable > seems arbitrary and "dirty" to me), but if you wanted to define a > shorter syntax, you could use something like x ~> i + x. That said, I > really don't see the value of not using function(x) [especially these > days when people are arguing for long variable names with the > justification that IDEs do all the work anyway], but as I said, my > argument was against the actual proposal, not general ideas about > syntax improvement. Cheers, Simon >> On 17/04/2020, at 3:53 AM, Sokol Serguei <sokol at insa-toulouse.fr> >> wrote: Simon, Thanks for replying. In what follows I won't try to >> argue (I understood that you find this a bad idea) but I would like >> to make clearer some of your point for me (and may be for others). Le >> 16/04/2020 ? 16:48, Simon Urbanek a ?crit : >>> Serguei, >>>> On 17/04/2020, at 2:24 AM, Sokol Serguei <sokol at 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. >>> It's not in any way "neater", not only is it less readable, it's >>> just plain wrong. What if the expression returned a function? >> do you mean like in l=sapply(1:3, function(i) function(x) i+x) >> l[[1]](3) # 4 l[[2]](3) # 5 This is indeed a corner case but a pair >> of () or {} can keep wsapply() in course: l=wsapply(1:3, (function(x) >> .+x)) l[[1]](3) # 4 l[[2]](3) # 5 >>> How do you know that you don't want to apply the result of the call? >> A small example (if it is significantly different from the one above) >> would be very helpful for me to understand this point. >>> For the same reason the implementation below won't work - very often >>> you just pass a symbol that evaluates to a function and always en >>> expression that returns a function and there is no way to >>> distinguish that from your new proposed syntax. >> Even with () or {} around such "dotted" expression? Best, Serguei. >>> When you feel compelled to use substitute() you should hear alarm >>> bells that something is wrong ;). You can certainly write a new >>> function that uses a different syntax (and I'm sure someone has >>> already done that in the package space), but what you propose is >>> incompatible with *apply in R (and very much not R syntax). Cheers, >>> Simon >>>> To illustrate a possible implementation, I propose a wrapper >>>> example for sapply(): wsapply=function(l, fun, ...) { >>>> s=substitute(fun) if (is.name(s) || is.call(s) && >>>> s[[1]]==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 at r-project.org mailing list >>>> https://stat.ethz.ch/mailman/listinfo/r-devel >
You can get pretty close to that already using fn$ in the gsubfn package:> library(gsubfn) > fn$sapply(split(mtcars, mtcars$cyl), x ~ summary(lm(mpg ~ wt, x))$r.squared)4 6 8 0.5086326 0.4645102 0.4229655 It is not specific to sapply but rather fn$ can preface most functions. If the only free variables are the arguments to the function then you can omit the left hand side of the formula, i.e. the arguments to the function are implied by the free variables in the right hand side. Here x is the implied argument to the function because it is a free variable. We did not have use the name x. Any name could be used. It is the fact that it is a free variable, not its name, that matters.> fn$sapply(split(mtcars, mtcars$cyl), ~ sum(dim(x)))4 6 8 22 18 25 On Fri, Apr 17, 2020 at 4:11 AM Sokol Serguei <sokol at insa-toulouse.fr> wrote:> > Thanks Simon, > > Now, I see better your argument. > > Le 16/04/2020 ? 22:48, Simon Urbanek a ?crit : > > ... I'm not arguing against the principle, I'm arguing about your > > particular proposal as it is inconsistent and not general. > This sounds promising for me. May be in a (new?) future, R core will > come with a correct proposal for this principle? > Meanwhile, to avoid substitute(), I'll look on the side of formula > syntax deviation as your example x ~> i + x suggested. > > Best, > Serguei. > > > Personally, I find the current syntax much clearer and readable > > (defining anything by convention like . being the function variable > > seems arbitrary and "dirty" to me), but if you wanted to define a > > shorter syntax, you could use something like x ~> i + x. That said, I > > really don't see the value of not using function(x) [especially these > > days when people are arguing for long variable names with the > > justification that IDEs do all the work anyway], but as I said, my > > argument was against the actual proposal, not general ideas about > > syntax improvement. Cheers, Simon > >> On 17/04/2020, at 3:53 AM, Sokol Serguei <sokol at insa-toulouse.fr> > >> wrote: Simon, Thanks for replying. In what follows I won't try to > >> argue (I understood that you find this a bad idea) but I would like > >> to make clearer some of your point for me (and may be for others). Le > >> 16/04/2020 ? 16:48, Simon Urbanek a ?crit : > >>> Serguei, > >>>> On 17/04/2020, at 2:24 AM, Sokol Serguei <sokol at 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. > >>> It's not in any way "neater", not only is it less readable, it's > >>> just plain wrong. What if the expression returned a function? > >> do you mean like in l=sapply(1:3, function(i) function(x) i+x) > >> l[[1]](3) # 4 l[[2]](3) # 5 This is indeed a corner case but a pair > >> of () or {} can keep wsapply() in course: l=wsapply(1:3, (function(x) > >> .+x)) l[[1]](3) # 4 l[[2]](3) # 5 > >>> How do you know that you don't want to apply the result of the call? > >> A small example (if it is significantly different from the one above) > >> would be very helpful for me to understand this point. > >>> For the same reason the implementation below won't work - very often > >>> you just pass a symbol that evaluates to a function and always en > >>> expression that returns a function and there is no way to > >>> distinguish that from your new proposed syntax. > >> Even with () or {} around such "dotted" expression? Best, Serguei. > >>> When you feel compelled to use substitute() you should hear alarm > >>> bells that something is wrong ;). You can certainly write a new > >>> function that uses a different syntax (and I'm sure someone has > >>> already done that in the package space), but what you propose is > >>> incompatible with *apply in R (and very much not R syntax). Cheers, > >>> Simon > >>>> To illustrate a possible implementation, I propose a wrapper > >>>> example for sapply(): wsapply=function(l, fun, ...) { > >>>> s=substitute(fun) if (is.name(s) || is.call(s) && > >>>> s[[1]]==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 at r-project.org mailing list > >>>> https://stat.ethz.ch/mailman/listinfo/r-devel > > > > ______________________________________________ > R-devel at r-project.org 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
Le 19/04/2020 ? 20:46, Gabor Grothendieck a ?crit?:> You can get pretty close to that already using fn$ in the gsubfn package: >> library(gsubfn) fn$sapply(split(mtcars, mtcars$cyl), x ~ >> summary(lm(mpg ~ wt, x))$r.squared) > 4 6 8 0.5086326 0.4645102 0.4229655Right, I thought about similar syntax but this implementation has similar flaws pointed by Simon, i.e. it reduces the domain of valid inputs (though not on the same parameters). Take an example: library(gsubfn) fn$sapply(quote(x+y), as.character) #Error in lapply(X = X, FUN = FUN, ...) : object 'x' not found while sapply(quote(x+y), as.character) #[1] "+" "x" "y" This makes me think that it could be advantageous to replace match.fun(FUN) in *apply() family by as.function(FUN) with obvious additional methods: as.function.character <- function(x) match.fun(x) as.function.name <- function(x) match.fun(x) Such replacement would leave current usage of *apply() as is but at the same time would leave enough space for users who want to adapt *apply() to their objects like formula or whatever class that is currently not convertible to functions by match.fun() Would it be possible? Best, Serguei.> It is not specific to sapply but rather fn$ can preface most > functions. If the only free variables are the arguments to the > function then you can omit the left hand side of the formula, i.e. the > arguments to the function are implied by the free variables in the > right hand side. Here x is the implied argument to the function > because it is a free variable. We did not have use the name x. Any > name could be used. It is the fact that it is a free variable, not its > name, that matters. >> fn$sapply(split(mtcars, mtcars$cyl), ~ sum(dim(x))) > 4 6 8 22 18 25 On Fri, Apr 17, 2020 at 4:11 AM Sokol Serguei > <sokol at insa-toulouse.fr> wrote: >> Thanks Simon, Now, I see better your argument. Le 16/04/2020 ? 22:48, >> Simon Urbanek a ?crit : >>> ... I'm not arguing against the principle, I'm arguing about your >>> particular proposal as it is inconsistent and not general. >> This sounds promising for me. May be in a (new?) future, R core will >> come with a correct proposal for this principle? Meanwhile, to avoid >> substitute(), I'll look on the side of formula syntax deviation as >> your example x ~> i + x suggested. Best, Serguei. >>> Personally, I find the current syntax much clearer and readable >>> (defining anything by convention like . being the function variable >>> seems arbitrary and "dirty" to me), but if you wanted to define a >>> shorter syntax, you could use something like x ~> i + x. That said, >>> I really don't see the value of not using function(x) [especially >>> these days when people are arguing for long variable names with the >>> justification that IDEs do all the work anyway], but as I said, my >>> argument was against the actual proposal, not general ideas about >>> syntax improvement. Cheers, Simon >>>> On 17/04/2020, at 3:53 AM, Sokol Serguei <sokol at insa-toulouse.fr> >>>> wrote: Simon, Thanks for replying. In what follows I won't try to >>>> argue (I understood that you find this a bad idea) but I would like >>>> to make clearer some of your point for me (and may be for others). >>>> Le 16/04/2020 ? 16:48, Simon Urbanek a ?crit : >>>>> Serguei, >>>>>> On 17/04/2020, at 2:24 AM, Sokol Serguei <sokol at 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. >>>>> It's not in any way "neater", not only is it less readable, it's >>>>> just plain wrong. What if the expression returned a function? >>>> do you mean like in l=sapply(1:3, function(i) function(x) i+x) >>>> l[[1]](3) # 4 l[[2]](3) # 5 This is indeed a corner case but a pair >>>> of () or {} can keep wsapply() in course: l=wsapply(1:3, >>>> (function(x) .+x)) l[[1]](3) # 4 l[[2]](3) # 5 >>>>> How do you know that you don't want to apply the result of the call? >>>> A small example (if it is significantly different from the one >>>> above) would be very helpful for me to understand this point. >>>>> For the same reason the implementation below won't work - very >>>>> often you just pass a symbol that evaluates to a function and >>>>> always en expression that returns a function and there is no way >>>>> to distinguish that from your new proposed syntax. >>>> Even with () or {} around such "dotted" expression? Best, Serguei. >>>>> When you feel compelled to use substitute() you should hear alarm >>>>> bells that something is wrong ;). You can certainly write a new >>>>> function that uses a different syntax (and I'm sure someone has >>>>> already done that in the package space), but what you propose is >>>>> incompatible with *apply in R (and very much not R syntax). >>>>> Cheers, Simon >>>>>> To illustrate a possible implementation, I propose a wrapper >>>>>> example for sapply(): wsapply=function(l, fun, ...) { >>>>>> s=substitute(fun) if (is.name(s) || is.call(s) && >>>>>> s[[1]]==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 at r-project.org mailing list >>>>>> https://stat.ethz.ch/mailman/listinfo/r-devel >> ______________________________________________ R-devel at r-project.org >> mailing list https://stat.ethz.ch/mailman/listinfo/r-devel >