首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >为什么,对于整数向量x,作为(x,“数值”)触发加载额外的S4方法的胁迫?

为什么,对于整数向量x,作为(x,“数值”)触发加载额外的S4方法的胁迫?
EN

Stack Overflow用户
提问于 2015-12-07 11:39:07
回答 2查看 899关注 0票数 42

虽然我的问题与this recent one有关,但我怀疑它的答案将与R的S4对象系统的详细工作有关。

我所期望的:

(TLDR; --所有迹象表明,as(4L, "numeric")应该分派给一个函数,该函数的主体使用as.numeric(4L)将其转换为"numeric"向量。)

每当使用as(object, Class)将对象转换为所需的Class时,实际上是在触发对coerce()的幕后调用。反过来,coerce()有许多基于函数调用签名的方法--这里是它的第一个和第二个参数的类。要查看所有可用S4 coerce()方法的列表,可以运行showMethods("coerce")

这样做表明,只有一种方法可以转换为类"numeric"。这是一个有签名的from="ANY", to="numeric"

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
showMethods("coerce")
# Function: coerce (package methods)
# from="ANY", to="array"
#      ... snip ... 
# from="ANY", to="numeric"
#      ... snip ...

该方法使用as.numeric()执行其转换:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
getMethod("coerce", c("ANY", "numeric"))
# Method Definition:
# 
# function (from, to, strict = TRUE) 
# {
#     value <- as.numeric(from)
#     if (strict) 
#         attributes(value) <- NULL
#     value
# }
# <environment: namespace:methods>
# 
# Signatures:
#         from  to       
# target  "ANY" "numeric"
# defined "ANY" "numeric"

考虑到它的签名,以及它是转换为类coerce()的唯一"numeric"方法,我希望上面显示的函数就是通过调用as(4L, "numeric")发送到的函数。只有运行以下两次检查才能增强这种期望。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
## (1) There isn't (apparently!) any specific method for "integer"-->"numeric"
##     conversion
getMethod("coerce", c("integer", "numeric"))
# Error in getMethod("coerce", c("integer", "numeric")) : 
#   no method found for function 'coerce' and signature integer, numeric

## (2) This says that the "ANY"-->"numeric" method will be used for "integer"-->"numeric"
##     conversion    
selectMethod("coerce",  signature=c("integer", "numeric"))
# Method Definition:
# 
# function (from, to, strict = TRUE) 
# {
#     value <- as.numeric(from)
#     if (strict) 
#         attributes(value) <- NULL
#     value
# }
# <environment: namespace:methods>
# 
# Signatures:
#         from      to       
# target  "integer" "numeric"
# defined "ANY"     "numeric"

实际发生了什么:

(TLDR;,实际上,调用as(4L, "numeric")将加载和分派给一个根本不做任何操作的方法)。

尽管有上面提到的所有指示,as(4L, "numeric")不会将带有签名c("ANY", "numeric")的调用分派给coerce()方法。

这里有几种方法可以证明:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
## (1) as.numeric() would do the job, but as(..., "numeric") does not
class(as(4L, "numeric"))
#[1] "integer"
class(as.numeric(4L))
# [1] "numeric"

## (2) Tracing shows that the "generic" method isn't called
trace("coerce", signature=c("ANY", "numeric"))

as(c(FALSE, TRUE), "numeric")        ## <-- It's called for "logical" vectors
# Tracing asMethod(object) on entry   
# [1] 0 1

as(c("1", "2"), "numeric")           ## <-- and for "character" vectors
# Tracing asMethod(object) on entry   
# [1] 1 2    

as(c(1L, 2L), "numeric")             ## <-- but not for "integer" vectors 
# [1] 1 2

untrace("coerce")

那么,使用了什么方法呢?显然,调用as(4L, "numeric")的行为在coerce()的方法列表中添加了一个新的S4方法,这就是所使用的方法。

(将以下调用的结果与我们尝试进行的第一次"integer""character"转换之前的结果进行比较。)

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
## At least one conversion needs to be attempted before the  
## "integer"-->"numeric" method appears.
as(4L, "numeric")  

## (1) Now the methods table shows a new "integer"-->"numeric" specific method   
showMethods("coerce")    
# Function: coerce (package methods)
# from="ANY", to="array"
#      ... snip ... 
# from="ANY", to="numeric"
#      ... snip ...
# from="integer", to="numeric"        ## <-- Here's the new method
#      ... snip ...

## (2) selectMethod now tells a different story
selectMethod("coerce",  signature=c("integer", "numeric"))
# Method Definition:
# 
# function (from, to = "numeric", strict = TRUE) 
# if (strict) {
#     class(from) <- "numeric"
#     from
# } else from
# <environment: namespace:methods>
# 
# Signatures:
#         from      to       
# target  "integer" "numeric"
# defined "integer" "numeric"

我的问题:

  1. 为什么as(4L, "numeric")不分派给可用的coerce()方法用于signature=c("ANY", "numeric")
  2. 它如何/为什么要向S4方法表中添加一个新方法?
  3. (在R的源代码或其他地方) coerce()方法的定义是从哪里来的?
EN

回答 2

Stack Overflow用户

发布于 2016-09-22 02:02:43

我不确定能否详尽地回答你的问题,但我会尽力的。

as()函数的帮助声明:

函数“as”将“object”转换为类“class”的对象。在这样做的过程中,它使用了S4类和方法,但以某种特殊的方式应用了一个“强制方法”。 ..。 假设‘object’还不是所需的类,因为‘first’在函数表中查找签名‘c(from= class(object),to = class )’的方法,方法选择的方式与方法选择进行初始查找的方式相同。 ..。 如果找不到任何方法,“as”就会查找一个方法。首先,如果“类”或“类(对象)”是另一个类的超类,则类定义将包含构造强制方法所需的信息。在通常情况下,子类包含超类(即有其所有的时隙),则通过提取或替换继承的时隙来构造该方法。

如果您查看as()函数的代码(要查看它,输入as (不带括号!),这正是您所能看到的。到R控制台)-见下文。首先,它寻找一个asMethod,如果它找不到它试图构造的任何一个,最后它执行它:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
if (strict) 
    asMethod(object)
else asMethod(object, strict = FALSE)

当您复制粘贴as()函数的代码并定义自己的函数(让我们称之为myas() )时,您可以在刚才提到的if (strict)上面插入一个print(asMethod),以获得用于胁迫的函数。在这种情况下,输出是:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
> myas(4L, 'numeric')
function (from, to = "numeric", strict = TRUE) 
if (strict) {
    class(from) <- "numeric"
    from
} else from
<environment: namespace:methods>
attr(,"target")
An object of class “signature”
     from        to 
"integer" "numeric" 
attr(,"defined")
An object of class “signature”
     from        to 
"integer" "numeric" 
attr(,"generic")
[1] "coerce"
attr(,"generic")attr(,"package")
[1] "methods"
attr(,"class")
[1] "MethodDefinition"
attr(,"class")attr(,"package")
[1] "methods"
attr(,"source")
[1] "function (from, to = \"numeric\", strict = TRUE) "
[2] "if (strict) {"                                    
[3] "    class(from) <- \"numeric\""                   
[4] "    from"                                         
[5] "} else from"                                      
[1] 4

因此,正如您可以看到的(查看attr(,"source")),as(4L, 'numeric')只是将类numeric分配给输入对象并返回它。因此,以下两个片段是等价的(在本例中!):

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
> # Snippet 1
> x = 4L
> x = as(x, 'numeric')

> # Snippet 2
> x = 4L
> class(x) <- 'numeric'

有趣的是,两者都是“一无所有”。更有趣的是,相反的,它起作用的方式是:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
> x = 4
> class(x)
[1] "numeric"
> class(x) <- 'integer'
> class(x)
[1] "integer"

我不太确定这一点(因为class方法似乎是用C实现的)--但我的猜测是,在分配类numeric时,它首先检查它是否已经是numeric。这可能是因为integernumeric (虽然不是double) --参见下面引用的“历史异常”:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
> x = 4L
> class(x)
[1] "integer"
> is.numeric(x)
[1] TRUE

关于as.numeric:这是一个通用方法,并调用as.double(),这就是它“工作”的原因(来自as.numeric上的R帮助):

这是一个历史异常,R有两个名字来表示它的浮点向量,‘double’和‘数值’(以前有‘that’)。 ‘’double‘是类型的名称。“数值”是模式的名称,也是隐式类的名称。

关于问题(1) - (3):魔法发生在as函数顶部的这四行中:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
where <- .classEnv(thisClass, mustFind = FALSE)
coerceFun <- getGeneric("coerce", where = where)
coerceMethods <- .getMethodsTable(coerceFun, environment(coerceFun), inherited = TRUE)
asMethod <- .quickCoerceSelect(thisClass, Class, coerceFun, coerceMethods, where)

对不起,我没时间钻研。

希望这能有所帮助。

票数 1
EN

Stack Overflow用户

发布于 2016-06-27 10:45:13

看看as()的源代码,它有两个部分。(为了清晰起见,缩短了源代码)。首先,它查找coerce()的现有方法,如上面所述。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
function (object, Class, strict = TRUE, ext = possibleExtends(thisClass, 
    Class)) 
{
    thisClass <- .class1(object)
    where <- .classEnv(thisClass, mustFind = FALSE)
    coerceFun <- getGeneric("coerce", where = where)
    coerceMethods <- .getMethodsTable(coerceFun, environment(coerceFun), 
        inherited = TRUE)
    asMethod <- .quickCoerceSelect(thisClass, Class, coerceFun, 
        coerceMethods, where)

    # No matching signatures from the coerce table!!!
    if (is.null(asMethod)) {
        sig <- c(from = thisClass, to = Class)
        asMethod <- selectMethod("coerce", sig, optional = TRUE, 
            useInherited = FALSE, fdef = coerceFun, mlist = getMethodsForDispatch(coerceFun))

如果没有找到任何方法,如本例所示,则尝试创建一个新方法,如下所示:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
        if (is.null(asMethod)) {
            canCache <- TRUE
            inherited <- FALSE

            # The integer vector is numeric!!!
            if (is(object, Class)) {
                ClassDef <- getClassDef(Class, where)
                if (identical(ext, FALSE)) {}
                else if (identical(ext, TRUE)) {}
                else {
                  test <- ext@test

                  # Create S4 coercion method here
                  asMethod <- .makeAsMethod(ext@coerce, ext@simple, 
                    Class, ClassDef, where)
                  canCache <- (!is(test, "function")) || identical(body(test), 
                    TRUE)
                }
            }
            if (is.null(asMethod)) {}
            else if (canCache) 
                asMethod <- .asCoerceMethod(asMethod, thisClass, 
                  ClassDef, FALSE, where)
            if (is.null(asMethod)) {}
            else if (canCache) {
                cacheMethod("coerce", sig, asMethod, fdef = coerceFun, 
                  inherited = inherited)
            }
        }
    }

    # Use newly created method on object here
    if (strict) 
        asMethod(object)
    else asMethod(object, strict = FALSE)

顺便说一句,如果您只处理基本的原子类型,我将坚持使用基本函数,并避免使用methods包;使用methods的唯一原因是处理S4对象。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/34141757

复制
相关文章
[剑指offer] 数值的整数次方 [剑指offer] 数值的整数次方
给定一个double类型的浮点数base和int类型的整数exponent。求base的exponent次方。
尾尾部落
2018/09/04
8650
[剑指offer] 数值的整数次方
		
			[剑指offer] 数值的整数次方
Vue3.x相对于Vue2.x的变化
ps: 上图中,一种颜色代表一个功能,我们可以看到Options API的功能代码比较分散;Composition API则可以将同一个功能的逻辑,组织在一个函数内部,利于维护。
conanma
2021/11/03
8800
数值的整数次方
题目描述 给定一个double类型的浮点数base和int类型的整数exponent。求base的exponent次方。 保证base和exponent不同时为0
名字是乱打的
2022/05/13
4560
数值的整数次方
给定一个 double 类型的浮点数 x和 int 类型的整数 n,求 x 的 n 次方。
MickyInvQ
2021/12/17
5370
数值的整数次方
数值的整数次方
快速求幂算法 解法来自于:牛客网-试题广场-数值的整数次方 public class Solution { public double Power(double base, int exponent) { int n=Math.abs(exponent); if(n==0) return 1; if(n==1) return base; double result=Power(ba
2019/02/25
5130
数值的整数次方
在JavaScript中有一个库函数(Math.pow())可以对一个数进行次方运算,本文将实现一个类似pow功能的函数,欢迎各位感兴趣的开发者阅读本文。
神奇的程序员
2022/04/10
5330
数值的整数次方
为什么SpringBoot2.x官方首推Caffeine作为缓存框架?
Caffeine是一个高性能,高命中率,低内存占用,near optimal 的本地缓存,简单来说它是Guava Cache的优化加强版,有些文章把Caffeine称为“新一代的缓存”、“现代缓存之王”。本文将重点讲解Caffeine的高性能设计,以及对应部分的源码分析。
业余草
2020/12/16
7760
为什么SpringBoot2.x官方首推Caffeine作为缓存框架?
R获取数值向量的分位数值
如果我们手上有一个数值向量,怎么用R去获取这个向量的各个分位数值呢?我们来看个具体的例子
生信交流平台
2022/09/21
1.1K0
R获取数值向量的分位数值
数值的整数次方
给定一个double类型的浮点数base和int类型的整数exponent。求base的exponent次方。
用户3003813
2018/09/06
4680
linux下chmod +x的意思?为什么要进行chmod +x
首先对start.sh这个启动文件删除,然后使用rz命令上传了新的start.sh,然后发现还有进行下一步,chmod +x start.sh
全栈程序员站长
2022/09/14
4.6K0
linux下chmod +x的意思?为什么要进行chmod +x
X@X.X域名转向的实现
当你看到csdn@csdn.com时,你肯定把这当作电子邮件地址,其实这个不一定是邮件地址,有可能是域名。现在有越来越多的人开始使用这个形式的地址了。初看起来,你不要以为这个是一个什么非常了不起的技术,其实是一个非常简单的东西。
Java架构师必看
2021/03/22
9170
数值的整数次方_12
给定一个double类型的浮点数base和int类型的整数exponent。求base的exponent次方。
名字是乱打的
2021/12/23
2940
为什么用 if(0 == x) 而不是 if(x == 0) ?
大家好,今天跟大伙分享一个编程小技巧方面的知识:标题已经给出了,为什么有的人更愿意用 if ( 0 == x)而不是 if(x == 0)?
Power7089
2020/07/27
1.8K0
C语言中的宏陷阱 #define SQU(x) x*x
有同学写过或者想写这样的宏定义吗? 求两个或几个数的乘积: #define SQU(x) x*x 我们正常使用没有问题: 但如果这样写呢? 哎呀,竟然不是100了,难道SQU(10)和SQU(5+
编程范 源代码公司
2018/04/18
1.3K0
C语言中的宏陷阱 #define SQU(x) x*x
[Leetcode][python]Sqrt(x)/x 的平方根
二分搜索:值得注意的是右边可以直接设置为j=x/2+1,因为在(x/2+1)^2 > x。
蛮三刀酱
2019/03/26
8990
[Leetcode][python]Sqrt(x)/x 的平方根
python中的if x 与if x == True
测试一下时间,显然第一种略快一点。第二个多了比较的操作,略慢一点。并且,考虑到PEP的规范,运行速度和简洁性等方面,if x更加合适。此外,在python中判断为假的主要有:
生信编程日常
2020/04/01
2.9K0
2021-09-11:给你一个32位的有符号整数x,返回将x中的数
2021-09-11:给你一个32位的有符号整数x,返回将x中的数字部分反转后的结果。反转后整数超过 32 位的有符号整数的范围就返回0,假设环境不允许存储 64 位整数(有符号或无符号)。
福大大架构师每日一题
2021/09/11
6580
Openlayers 2.X加载天地图
在前面的章节,讲到了Arcgis for js加载天地图,在本节讲述如何在Openlayers 2.X的版本中加载天地图,并添加自己的wms服务。
牛老师讲GIS
2018/10/23
1.9K0
Openlayers 2.X加载天地图
点击加载更多

相似问题

as.vector(x)中的错误:没有将此S4类胁迫到向量的方法

11

<x>应为数值矩阵或数值向量

145

对于每个额外的"x",加上"y“

111

为什么对于整数,在Python3.x中,2*x*x比2*(x*x)快?

30

没有将这个S4类胁迫到向量以利用mclust的方法。

13
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文