5

I need to create additional name for my_function(i,x) (where i can be an integer from 1 to 25). I'd like it to work like this

  • my_function1(x) sames as my_function(1,x)
  • my_function2(x) sames as my_function(2,x)
  • my_function3(x) sames as my_function(3,x)
  • ...
  • my_function25(x) sames as my_function(25,x)

One way to do achieve this would be:

my_function1 <- function (x) my_function(1, x)
my_function2 <- function (x) my_function(2, x)
my_function3 <- function (x) my_function(3, x)
...

But since there are 25 of them it would be reasonable to make it in a loop. For this I've tried:

for(i in 1:25){
  assign(paste("my_function",i,sep=""),function(x) my_function(i,x))
}

but it doesn't work since i is passed by reference and in the end the result was

  • my_function1(x) sames as my_function(25,x)
  • my_function2(x) sames as my_function(25,x)
  • my_function3(x) sames as my_function(25,x)
  • ...

How can I pass "i" by value? Or perhaps there is some other way...

Why would I want to do this? I'm improving someones else R package in terms of efficiency but at the same time I need it to be compatible with old version.

Ari B. Friedman
  • 71,271
  • 35
  • 175
  • 235
LukaszJ
  • 123
  • 4
  • Welcome to SO. You'll find you get better answers if you post a [reproducible example](http://stackoverflow.com/questions/5963269/how-to-make-a-great-r-reproducible-example) next time. Or this time, since you can edit your post :-) – Ari B. Friedman May 05 '13 at 12:14
  • @AriB.Friedman Thanks :) Next time I will remember to write reproducible example. Curry looks very clean and it works perfect but in this case I'd rather use some standard R functions as I don't really want to install any extra packages. – LukaszJ May 05 '13 at 14:23

3 Answers3

6

This is called currying, and is a part of functional programming.

library(functional)

myf <- function(a,x) cat(a,x,"\n")
myf1 <- Curry(myf, a=1)
myf1(5)
for(i in seq(25)) assign(paste0("myf",i), Curry(myf,a=i) )
> myf15(5)
15 5

I guess there's an important question here as to why you'd want to do this. This seems like exactly the kind of thing you'd want arguments not many related functions for.

Ari B. Friedman
  • 71,271
  • 35
  • 175
  • 235
4

Well, you can achieve the same result, using base functions too.

The trick is to force (force) the evaluation of i at each iteration and assign your function in the .Globalenv (or the environment you like)

my_function <- function(a, b) a + b


lapply(1:10, function(i) {
    force(i)
    assign(paste0("my_function", i), function(x) my_function(i, x), envir = .GlobalEnv)
}
       )


my_function1(10)
## [1] 11

my_function9(10)
## [1] 19
dickoa
  • 18,217
  • 3
  • 36
  • 50
  • @SimonO101 thanks !!! I love the "there's more than one way to do it" philosophy in R, I was not aware of `Curry` as well and didn't think about `bquote` in this case. thks – dickoa May 05 '13 at 13:25
  • 2
    There's more than one way to do it, but there's only one way to not do it, and I really think this is something that should not be done... I bet the next question from the OP will be "how do I call `my_function${i}()` for some value of `i`? – Spacedman May 05 '13 at 14:23
2

I think bquote will help here:

for(i in 1:2){
  assign(paste("my_function",i,sep=""), bquote( function(x) my_function( i = .(i) , x ) ) )
}

>my_function2
# function(x) my_function(i = 2L, x)

But the point still stands - why would you want to do this?

Simon O'Hanlon
  • 58,647
  • 14
  • 142
  • 184
  • Well, I'm improving someones else R package in terms of efficiency but at the same time I need it to be compatible with old version. Thanks for the solution! – LukaszJ May 05 '13 at 14:27