[R] Curry with `[.function` ?

Gabor Grothendieck ggrothendieck at gmail.com
Mon Mar 21 15:53:52 CET 2011


On Mon, Mar 21, 2011 at 8:46 AM, Kenn Konstabel <lebatsnok at 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.

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



More information about the R-help mailing list