On Mon, Mar 21, 2011 at 12:20 PM, Kenn Konstabel <lebats...@gmail.com> wrote: > On Mon, Mar 21, 2011 at 2:53 PM, Gabor Grothendieck > <ggrothendi...@gmail.com> wrote: >> >> On Mon, Mar 21, 2011 at 8:46 AM, Kenn Konstabel <lebats...@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 >
Using gsubfn's fn$ the trick is to use the identity function: library(gsubfn) mean.trim.1 <- fn$identity(~ mean(x, trim = 0.1)) Now mean.trim.1(x) is the same as mean(x, trim = 0.1) or in one line: fn$identity(~ mean(x, trim = 0.1))(c(.99, 1e20)) -- Statistics & Software Consulting GKX Group, GKX Associates Inc. tel: 1-877-GKX-GROUP email: ggrothendieck at gmail.com ______________________________________________ R-help@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.