【问题标题】:Operator overloading for functions in R - strange behaviorR中函数的运算符重载 - 奇怪的行为
【发布时间】:2013-03-04 03:50:00
【问题描述】:

不幸的是,像(f+g)(3) 这样的东西,其中 f 和 g 都是一元函数在 R 中不起作用。因此我尝试通过以下方式重载一元函数的“+”运算符:

"+.function" = function(e1, e2){
  return(function(x) e1(x) + e2(x))
}

但是,如果我尝试使用它,这将无济于事。代码

 a = function(x) 2*x
 (a+a)(2)

产生与 +.function 甚至没有定义一样的错误。

玩了一段时间后,我发现实际上有可能以这种方式添加函数:如果函数是引用类的成员函数,这可行!即,以下代码(连同上面的“+”定义)

clsA = setRefClass("clsA", 
  methods = list(
    b = function(x) 2*x
  ))

inst_a = clsA$new()
(inst_a$b + inst_a$b)(2)

返回“8”(如预期的那样)。因此,对于我的问题,我已经有了某种解决方法。现在我的问题是:

这种奇怪行为的原因是什么?为什么+.function 不关心“普通”函数而是类成员函数?有谁知道如何将运算符“扩展”为常用功能?

【问题讨论】:

  • 如果你重新定义a的类,例如像class(a)
  • 很好,这行得通:-) 好吧,人们仍然可以认为这仍然是一种解决方法,但我认为它比我对参考类的想法“更聪明”得多。非常感谢你的这个想法!

标签: r oop class function reference-class


【解决方案1】:

作为一种解决方法,您可以像这样定义special operator (%...%):

"%+%" <- function(e1, e2) {
  return(function(x) e1(x) + e2(x))
}

a <- function(x) 2*x
(a %+% a)(2) # == 8

【讨论】:

  • 这对我产生了与"+.function" 方法相同的错误。
  • 抱歉,忘记用%+%替换+...现在应该可以使用了
  • 谢谢,虽然我误解了 %+%..
  • 当然可以;但是%+% 看起来并不那么聪明。并将其推广到 -, *, /,... 会产生很多行代码。有了上面的想法,Ops.function 也是可能的,将此运算符推广到 +、-、* 等......
  • @Patrick 是的,我同意。然而,即使是标准 R 也使用 %...% 函数(例如 %*% 用于矩阵乘法或%/% 用于整数除法)。
【解决方案2】:

如果您重新定义a 的类,例如class(a)&lt;-"ownfunction"(或者更好的是class(a)&lt;-c("ownfunction","function"),并将您的"+.function" 设置为"+.ownfunction",那么(a+a)(2) 有效。

似乎function 类被以某种特殊方式处理:如果你运行debug("+.function");(a+a)(2),你会看到"+.function" 甚至没有被调用。

编辑:见 cmets。

【讨论】:

  • 根据您的想法:如果我重新定义 class(a)&lt;-"function" 而不是我原来的 +.function 运算符适用于 a 以及类方法。我认为这将是最聪明的解决方案。
  • @Patrick 这是真的。我相信会发生这种情况,因为在class(a) &lt;- "function" 之后,a 具有类属性"function",而普通函数不是这种情况。但是,在这两种情况下,class(a) 都会返回 "function"
  • 关于这个解决方案的另一条评论:为了也允许像 (f+g+h)(2) 这样的表达式,应该使用 { res = function(x) e1(x) + e2(x); class(res) = "function"; return(res) } 另外:使用 ... 而不是 x 还允许 n -ary 函数,即 (u+v)(2,2)。并将+ 分别替换为Ops.Primitive(.Generic) 可以推广解决方案。
  • 出现这种情况的原因是is.object(function() {})FALSE,所以不会发生内部S3 dispatch。这是一种性能优化,可避免使用基本类型时方法分派的开销。
  • @JoshO'Brien 没有设置 OBJECT 位的基本类型。您要么必须添加类属性,要么使用 S4 对象。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-04-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-02-29
  • 1970-01-01
  • 2020-09-08
相关资源
最近更新 更多