23

Is there a way to compare whether two function objects are the same?

m <- mean
m == mean ## don't work

## this seems not to be the correct way:
functionBody(mean)==functionBody(m)

EDIT: Some more details. I have a function with two arguments (a matrix and a user-defined function which is applied columnwise, e.g. mean, median, ...). If the function is mean I want to use colMean instead (to save some running time).

foo <- function(m, fun) {
  #if (fun==mean) {
  #  return(colMeans(m));
  #} else {
    return(apply(m, 2, fun));
  #}
}
sgibb
  • 25,396
  • 3
  • 68
  • 74

3 Answers3

30

You can use identical:

identical(m,mean)
digEmAll
  • 56,430
  • 9
  • 115
  • 140
  • 4
    Counter-example: m <- function (y, ...) { UseMethod("mean") } ; m(c(1,2,3)) ; identical(mean, m) # [1] FALSE – IRTFM Mar 09 '12 at 18:42
  • 3
    @DWin: Obviously, this method checks only whether the two variables point to the same function, not whether the code used is the same. If the OP needed the latter, he/she wouldn't have written "this seems not to be the correct way" over the body check IMO... – digEmAll Mar 09 '12 at 20:10
  • @DWin: however, IMO equality for functions can be obtained only checking whether they refer to the same; otherwise, yes you can cope a couple of cases, but basically, as correctly pointed out in Basile's comment, the problem is undecidable... – digEmAll Mar 09 '12 at 20:15
  • I thought that function(x) (mean(x)} would be considered to be the "same" as function(y){mean(y)}. I assumed that a wizard (obviously not me) would come by and show us all how to use `substitute` using the formals(fn) as arguments on body(fn) to make that comparison. I do understand that this would not compare the equality of inputs and outputs, which would be Basile's more correct same-ness criterion. – IRTFM Mar 09 '12 at 20:16
  • @DWin: yep, probably something can be done for that case. But it doesn't change too much because a number (infinite) of other cases (e.g. `function(x){a=0;mean(x)+a}`) wouldn't be recognized. – digEmAll Mar 09 '12 at 20:42
  • @digEmAll @DWin : `identical` seems to be sufficient for my use case. The counter-example won't break my code. It will only slow down the calculation a little bit. – sgibb Mar 10 '12 at 10:00
8

I use isTRUE(all.equal(function1,function2)), but this suffers from similar drawbacks to the other methods.

Interestingly though, all.equal gives a nice summary of how the two operands differ (try all.equal(function1,function2).

mathematical.coffee
  • 55,977
  • 11
  • 154
  • 194
3

You can convert the functions to strings, and compare those strings.

equal_functions <- function(f,g)
  all( 
    capture.output(print(f)) ==
    capture.output(print(g))
  )
equal_functions(function(x) x, function(x) x) # TRUE

But functions that differ for non-essential reasons will be seen as different.

equal_functions(function(x) x, function(u) u) # FALSE
equal_functions(
  function(x) x, 
  function(x) 
    x
) # FALSE
Vincent Zoonekynd
  • 31,893
  • 5
  • 69
  • 78