如何让vctrs S3类与基础S3类算术运算时抛出错误?
vctrs自定义S3类算术运算的异常行为问题
问题描述
学习vctrs包《s3-vector》文档的'Arithmetic'章节创建自定义S3类时,发现异常行为:
- 自定义类与R基础S3类(如
factor、Date、POSIXct)执行算术运算时,仅触发警告却仍完成运算,未抛出错误终止流程 - 但自定义类与内置类型(如
integer)运算时,会正常抛出错误并终止运算
以文档中示例的<vctrs_meter>类复现了该问题,期望基础S3类的算术运算能和内置类型保持一致,直接抛出错误。已在GitHub提交相关issue,认为该行为需要在文档中补充说明或修正。
复现代码及运行结果
按文档定义<vctrs_meter>类
library(vctrs) #> Warning: package 'vctrs' was built under R version 4.2.3 meter <- function(x) { x <- vec_cast(x, double()) new_meter(x) } new_meter <- function(x) { stopifnot(is.double(x)) new_vctr(x, class = "vctrs_meter") } format.vctrs_meter <- function(x, ...) { paste0(format(vec_data(x)), " m") } vec_arith.vctrs_meter <- function(op, x, y, ...) { UseMethod("vec_arith.vctrs_meter", y) } vec_arith.vctrs_meter.default <- function(op, x, y, ...) { stop_incompatible_op(op, x, y) } vec_arith.vctrs_meter.vctrs_meter <- function(op, x, y, ...) { switch( op, "+" = , "-" = new_meter(vec_arith_base(op, x, y)), "/" = vec_arith_base(op, x, y), stop_incompatible_op(op, x, y) ) }
内置类型运算(符合预期)
# 同类型运算正常执行 meter(10) + meter(1) #> <vctrs_meter[1]> #> [1] 11 m # 与integer运算抛出错误,符合预期 meter(10) + 1L #> Error in `vec_arith()`: #> ! <vctrs_meter> + <integer> is not permitted #> Backtrace: #> ▆ #> 1. └─vctrs:::`+.vctrs_vctr`(meter(10), 1L) #> 2. ├─vctrs::vec_arith("+", e1, e2) #> 3. ├─global vec_arith.vctrs_meter("+", e1, e2) #> 4. └─global vec_arith.vctrs_meter.default("+", e1, e2) #> 5. └─vctrs::stop_incompatible_op(op, x, y) #> 6. └─vctrs:::stop_incompatible(...) #> 7. └─vctrs:::stop_vctrs(...) #> 8. └─rlang::abort(message, class = c(class, "vctrs_error"), ..., call = call)
基础S3类运算(不符合预期)
# 与factor运算仅出警告,仍完成运算 meter(1) + factor("hi") #> Warning: Incompatible methods ("+.vctrs_vctr", "Ops.factor") for "+" #> <vctrs_meter[1]> #> [1] 2 m # 与Date运算仅出警告,仍完成运算 meter(1) + Sys.Date() #> Warning: Incompatible methods ("+.vctrs_vctr", "+.Date") for "+" #> <vctrs_meter[1]> #> [1] 19537 m # 与POSIXct运算仅出警告,仍完成运算 meter(1) + as.POSIXct(Sys.Date()) #> Warning: Incompatible methods ("+.vctrs_vctr", "+.POSIXt") for "+" #> <vctrs_meter[1]> #> [1] 1687910401 m
Created on 2023-06-28 with reprex v2.0.2
内容的提问来源于stack exchange,提问作者wurli
相关产品推荐
相关产品推荐

