Re: [R] Curry with `[.function` ?

From: Kenn Konstabel <lebatsnok_at_gmail.com>
Date: Mon, 21 Mar 2011 16:20:35 +0000

On Mon, Mar 21, 2011 at 2:53 PM, Gabor Grothendieck <ggrothendieck_at_gmail.com
> wrote:

> On Mon, Mar 21, 2011 at 8:46 AM, Kenn Konstabel <lebatsnok@gmail.com>
> wrote:
> > Dear all,
> >
> > I sometimes use the following function:
> >
> > Curry <- function(FUN,...) {
> > # by Byron Ellis,
> > https://stat.ethz.ch/pipermail/r-devel/2007-November/047318.html
> > .orig <- list(...)
> > function(...) do.call(FUN,c(.orig,list(...)))
> > }
> >
> > ... and have thought it might be convenient to have a method for [ doing
> > this. As a simple example,
> >
> >> apply(M, 1, mean[trim=0.1]) # hypothetical equivalent to apply(M, 1,
> > Curry(mean, trim=0.1))
> >
> > would be easier to understand than passing arguments by ...
> >
> >> apply(M, 1, mean, trim=0.1)
> >
> > and much shorter than using an anonymous function
> >
> >> apply(M, 1, function(x) mean(x, trim=0.1)
> >
> > This would be much more useful for complicated functions that may take
> > several functions as arguments. For example (my real examples are too
> long
> > but this seems general enough),
> >
> > foo <- function(x, ...) {
> > dots <- list(...)
> > mapply(function(f) f(x), dots)
> > }
> >
> > foo(1:10, mean, sd)
> > foo(c(1:10, NA), mean, mean[trim=0.1, na.rm=TRUE], sd[na.rm=TRUE])
> >
> > Defining `[.function` <- Curry won't help:
> >
> >> mean[trim=0.1]
> > Error in mean[trim = 0.1] : object of type 'closure' is not subsettable
> >
> > One can write summary and other methods for class "function" without such
> > problems, so this has something to do with [ being a primitive function
> and
> > not using UseMethod, it would be foolish to re-define it as an "ordinary"
> > generic function.
> >
> > Redefining mean as structure(mean, class="function") will make it work
> but
> > then one would have to do it for all functions which is not feasible.
> >
> >> class(mean) <- class(mean)
> >> class(sd)<-class(sd)
> >> foo(c(1:10, NA), mean, mean[na.rm=TRUE], mean[trim=0.1, na.rm=TRUE],
> > sd[na.rm=TRUE])
> > [1] NA 5.500000 5.500000 3.027650
> >
> > Or one could define a short-named function (say, .) doing this:
> >
> >> rm(mean, sd) ## removing the modified copies from global environment
> >> .<-function(x) structure(x, class=class(x))
> >> foo(c(1:10, NA), mean, .(mean)[na.rm=TRUE], .(mean)[trim=0.1,
> na.rm=TRUE],
> > .(sd)[na.rm=TRUE])
> >
> > But this is not as nice. (And neither is replacing "[" with "Curry" by
> using
> > substitute et al. inside `foo`, - this would make it usable only within
> > functions that one could be bothered to redefine this way - probably
> none.)
> >
> > Thanks in advance for any ideas and comments (including the ones saying
> that
> > this is an awful idea)

>

> If the aim is to find some short form to express functions then
> gsubfn's fn$ construct provides a way. It allows you to specify
> functions using formula notation. The left hand side of the formula
> is the arguments and the right hand side is the body. If no args are
> specified then it uses the free variables in the body in the order
> encountered to form the args. Thus one could write the following.
> (Since no args were specified and the right hand side uses the free
> variable x it assumes that there is a single arg x.)
>

> library(gsubfn)
> fn$apply(longley, 2, ~ mean(x, trim = 0.1))
> fn$lapply(longley, ~ mean(x, trim = 0.1))
> fn$sapply(longley, ~ mean(x, trim = 0.1))
>

> fn$ can preface just about any function. It does not have to be one
> of the above. See ?fn and http://gsubfn.googlecode.com for more info.
>
>
Thanks a lot! This is not exactly what I meant but it's a very useful hint. The idea was to find a concise way of using function with different default values for some of the arguments or to "fix" some of the arguments so that the result is a unary function.

I couldn't find a way to do it with gsubfn package directly (although maybe I should have another look) but by stealing some of your ideas:

. <- structure(NA, class="rice")
`$.rice` <- function(x,y) structure(match.fun(y), class="function") `[.function` <- function(FUN,...) {

   # https://stat.ethz.ch/pipermail/r-devel/2007-November/047318.html    .orig <- list(...)
   function(...) do.call(FUN,c(.orig,list(...)))    }

.$mean[trim=0.1](c(0:99,1e+20))
# 50

Thanks again,

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

        [[alternative HTML version deleted]]



R-help_at_r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-help PLEASE do read the posting guide http://www.R-project.org/posting-guide.html and provide commented, minimal, self-contained, reproducible code. Received on Mon 21 Mar 2011 - 16:24:45 GMT

Archive maintained by Robert King, hosted by the discipline of statistics at the University of Newcastle, Australia.
Archive generated by hypermail 2.2.0, at Mon 21 Mar 2011 - 17:00:23 GMT.

Mailing list information is available at https://stat.ethz.ch/mailman/listinfo/r-help. Please read the posting guide before posting to the list.

list of date sections of archive