覆盖非默认方法并避免递归

时间:2017-09-22 13:53:00

标签: r recursion dispatch generic-function

使用泛型函数系统调度调用原始方法的修改方法时,哪些编程原则可以帮助我避免递归?

背景

由于here所述的原因,我对bit64::as.integer64.character()的行为不满意,所以我写了一个解决方法函数,调用bit64::as.integer64()然后制作一些更改输出:

test_string <- c('1234','5678','', 'Help me Stack Overflow')

# illustration of undesired behavior:
library(bit64)
as.integer64(test_string) # returns int64 [1] 1234 5678 0 <NA> without warning

# workaround:    
charToInt64 <- function(s){
  stopifnot( is.character(s) )
  x <- bit64::as.integer64(s)
  # as.integer64("") unexpectedly returns zero without warning.  
  # Overwrite this result to return NA without warning, similar to base as.integer("")
  x[s==""] <- NA_integer64_
  # as.integer64("ABC") unexpectedly returns zero without warning.
  # Overwrite this result to return NA with same coercion warning as base as.integer("ABC")
  bad_strings <- grepl('\\D',s)
  if( any(bad_strings) ){
    warning('NAs introduced by coercion')
    x[bad_strings] <- NA_integer64_  
  }
  x
}

# Demo of workaround -- this behavior mimics base as.integer():
charToInt64(test_string) # returns int64 [1] 1234 5678 <NA> <NA> with warning
charToInt64(head(test_string,-1)) # returns int64 [1] 1234 5678 <NA> without warning

到目前为止,这么好。

接下来,作为一项学习练习,我尝试使用此解决方法覆盖方法as.integer64.character()。 (如果我在这篇文章中滥用任何OOP术语,请向我道歉,请纠正我。)

我尝试了什么

第一次尝试(没有工作,无限递归)

天真地,我推断,因为我在我的变通方法函数中调用泛型函数bit64::as.integer64()时使命名空间显式化,所以我应该能够定义一个具有相同名称的方法,但是在全局环境,我可以打电话,而无需启动无限递归。

as.integer64.character <- charToInt64 # override method in global environment
as.integer64(test_string) # Error: C stack usage  19922992 is too close to the limit

第二次尝试(有效,但我不明白为什么)

通过调用字符串方法bit64::as.integer64(s)来替换对泛型函数bit64::as.integer64.character(s)的调用可以解决问题。

charToInt64v2 <- function(s){
  stopifnot( is.character(s) )
  x <- bit64::as.integer64.character(s) # this is the only change
  x[s==""] <- NA_integer64_
  bad_strings <- grepl('\\D',s)
  if( any(bad_strings) ){
    warning('NAs introduced by coercion')
    x[bad_strings] <- NA_integer64_  
  }
  x
}
as.integer64.character <- charToInt64v2 
as.integer64(test_string) # works as desired

回顾问题

为什么第一次尝试在第一次尝试失败时有效?我不明白namespaces和/或dispatch的含义是什么?

0 个答案:

没有答案