在使用泛型函数系统调度调用原始方法的修改方法时,哪些编程原则可以帮助我避免递归?
背景
由于此处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