[R] Modifying a function programmatically

Søren Højsgaard sorenh at math.aau.dk
Mon Feb 4 11:37:44 CET 2013


No, this is not really what I want. But I have (later) realized that what I am looking for can be achieved as shown below. I am just not sure how bullet-proof the solution is. Suggestions are welcome!
Regards
Søren

------------------------------------------

specialize <- function(ff, vals){
  expr1 <- as.expression(body(ff))
  expr2 <- do.call("substitute", list(expr1[[1]], vals))
  gg  <- formals(ff)
  idx <-match(names(vals), names(gg))
  gg  <- gg[-idx]
  as.function(c(gg, expr2))
  }

 ff  <- function(a,b=2,c=4){a+b+c}
 (ans<-specialize(ff, list(a=1)))
function (b = 2, c = 4) 
{
    1 + b + c
}
<environment: 0x0000000008b51c68>
 ans()
[1] 7
 ans(b=10)
[1] 15

 (ans<-specialize(rnorm, list(n=10)))
function (mean = 0, sd = 1) 
.Internal(rnorm(10, mean, sd))
<environment: 0x0000000008b5a0b8>
 ans()
 [1]  0.1783645319  2.1151344735 -0.6744270178  0.0009751497 -0.1477708270  0.1710790055
 [7] -0.0064331250  0.5935787352 -0.1426050990 -0.1390478788
 ans(sd=.0001)
 [1]  1.386604e-06 -6.616540e-05  6.592326e-05 -1.299638e-04  1.322658e-05 -4.515388e-05
 [7] -2.809639e-05 -5.719492e-05  1.554319e-04 -1.186992e-04




-----Original Message-----
From: Pascal Oettli [mailto:kridox at ymail.com] 
Sent: 4. februar 2013 11:11
To: Søren Højsgaard
Cc: r-help at r-project.org
Subject: Re: [R] Modifying a function programmatically

Hi,

Is it what you are looking for?

 > ff  <- function(a,b,c){a+b+c}

 > ff(1,10,12)
[1] 23

 > ff(589,2,4)
[1] 595

HTH,
Pascal


Le 04/02/2013 19:00, Søren Højsgaard a écrit :
> Dear list
>
> # I have a function
>   ff  <- function(a,b=2,c=4){a+b+c}
> # which I programmatically want to modify to a more specialized function in which a is replaced by 1
>   ff1 <- function(b=2,c=4){1+b+c}
>
> # I do as follows:
>   vals  <- list(a=1)
>   (expr1 <- as.expression(body(ff)))
> expression({
>      a + b + c
> })
>   (expr2 <- do.call("substitute", list(expr1[[1]], vals))) {
>      1 + b + c
> }
>
>   # This "works",
>   eval(expr2, list(b=10,c=12))
> [1] 23
>
>   # - but I would like a function. Hence I do:
>   ll  <- alist(b=, c=, eval(expr2))
>   ff2 <- as.function(ll)
>   ff2(b=10,c=12)
> [1] 23
>
>   # BUT I am only half-way where I want to be because the alist(b=, c=, ...)
>   # requires me plugin the remaining formals by hand. I do:
>   newformals <-setdiff(names(formals(ff)), names(vals))
>   vv         <- vector("list", length(newformals))
>   names(vv)  <- newformals
>   (hh <- c(vv, expr2))
> $b
> NULL
> $c
> NULL
> [[3]]
> {
>      1 + b + c
> }
>
>   (ff3 <- as.function(hh))
> function (b = NULL, c = NULL)
> {
>      1 + b + c
> }
>   ff3(10,12)
> [1] 23
>   # Hence I get the function that returns what I want (given the correct input)
>   # but the arguments will have default values that I don't want.
>   # I want to retain the original default values (if any)
>   ff1()
> [1] 7
>   ff3()
> numeric(0)
>
> I have two questions:
> 1) How to fix the above?
> 2) Aren't there more elegant alternatives?
>
> Any help would be appreciated.
> Regards
> Søren
>
>
> ______________________________________________
> 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.
>



More information about the R-help mailing list