You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 01:15:33