0

Not sure if this is possible but worth an ask. I need to be able to modify a function that is loaded into the global environment. For example, lets say I had a function like the below that returned the median of a vector

myVec<-c(1,2,3,4,5,5,5,6,7,8,9,10)

average<-function(x){
  median(x)
}

average(myVec)

Now I wanted to update the function to return the mean but without changing the overall structure of the function so I want to update average() so it becomes

average<-function(x){
  mean(x)
}

Is this possible? I'm guessing some form of writing the function to a temp file and calling readLines() and writeLines() but as of yet I've not had any success.

Frank
  • 66,179
  • 8
  • 96
  • 180
Morgan Ball
  • 760
  • 9
  • 23
  • 2
    If you want to overwrite the entire body of the function, there's `body(average) <- quote(mean(x))`. Rewriting an existing function at a finer level can get messy, I guess. – Frank Sep 07 '17 at 15:46
  • If you define a function twice the more recent one overwrites the older one so the more recent one will be used. – G. Grothendieck Sep 07 '17 at 15:48
  • The function I need to modify is more complex so I don't want to just redefine it. I need just modify one line from it being in memory and then append it to a list and save the list. – Morgan Ball Sep 07 '17 at 15:50
  • 3
    Self-modifying code tends to be very hard to debug. Normally instead one would define the original function to have the replaceable functionality be passed as an argument. That argument could itself be a function. – G. Grothendieck Sep 07 '17 at 15:53
  • Nice one thanks @Frank – Morgan Ball Sep 07 '17 at 15:53
  • True, this is a bit of a patch to a bunch of stored objects that I need to read into memory so not quite 'normal' :) – Morgan Ball Sep 07 '17 at 15:55
  • What do you even mean by "the overall structure of the function"? I don't see how changing just the body of the function is any different than overwriting the function. – MrFlick Sep 07 '17 at 15:55
  • I mean no changing the parameters, otherwise you could just have a argument to amend the code. `fun<-function(myVec,myAverage)` – Morgan Ball Sep 07 '17 at 15:56
  • 1
    Maybe you could give an example where the "structure" matters. It could be as simple/silly as `average = function(x){1+1; median(x)}` If your function is simple enough, maybe this will help: https://stackoverflow.com/q/2458013/ – Frank Sep 07 '17 at 15:58
  • Even better @Frank thanks – Morgan Ball Sep 07 '17 at 16:03
  • 1
    If the function has more than just a call to `median`, make sure you only replace the single function call and not the entire body. In this case, `body(average)[[2]][[1]] <- quote(mean)` is all you want to do. – Nathan Werth Sep 07 '17 at 16:09
  • Maybe also check out the 'trace' function. – Roland Sep 07 '17 at 16:54

1 Answers1

1

I believe you mean a closure:

myVec<-c(1,2,3,4,5,5,5,6,7,8,9,10)

# this will create your function
create.average <- function (fun) {
  my.average <- function (x) {
    fun(x)
  }
  return(my.average)
}
# define average as mean
average <- create.average(mean)
average(myVec)
mean(myVec) # only to verify result

# re-define average as median
average <- create.average(median)
average(myVec)
median(myVec) # only to verify result
r.user.05apr
  • 5,356
  • 3
  • 22
  • 39