gpt4 book ai didi

r - `getClasses()` 中默认环境的模糊变化(标准函数与正式 S4 方法)

转载 作者:行者123 更新时间:2023-12-01 13:54:41 25 4
gpt4 key购买 nike

我在弄清楚“环境嵌套”/词法范围方面到底发生了什么时遇到了一些麻烦:

问题

参数的默认值 where在函数中 getClasses()似乎取决于是否getClasses() 中被调用标准 R 函数 正式的 S4 方法 .由.externalCallerEnv()控制这似乎是懒惰评估的“对象”,因此导致了变化(见 编辑 下面)

问题

从正式 S4 方法内部调用时,如何设置 where到与 getClasses() 时的默认值相同的值在标准函数中调用?

插图

您将在下面找到上述“问题行为”的简短说明

1) 自定义类

我有许多当前来自 .GlobalEnv 的类定义.

让我们以这个人为代表

setRefClass("A", fields=list(x="numeric"))

2) 列出可用的类

通过论证 where , 功能 getClasses让我选择寻找类(class)的环境。

除了 .GlobalEnv,下面似乎到处都是因此找不到我的类(class);没关系:
classes <- getClasses()
> head(classes)
[1] "(" ".environment" ".externalptr" ".name" ".NULL"
[6] ".Other"
> "A" %in% classes
[1] FALSE

现在我看 .GlobalEnv并找到类(class) A只要;也没关系:
classes <- getClasses(where=.GlobalEnv)
> classes
[1] "A"
> "A" %in% classes
[1] TRUE

3)创建自定义标准查找函数

当我通过 getClasses 进行查找时成 标准功能 (这只是所需功能的第一部分,我想在该方法中计算 getClasses() 而不是将其返回值作为正式参数传递),一切仍然正常
foo1 <- function(where=.GlobalEnv) {
if (is.null(where)) {
x <- getClasses()
} else {
x <- getClasses(where=where)
}
return(x)
}
> foo1()
[1] "A"
> classes <- foo1(where=NULL)
> head(classes)
[1] "(" ".environment" ".externalptr" ".name" ".NULL"
[6] ".Other"
> "A" %in% classes
[1] FALSE

4) 创建正式的 S4 方法

然而,一旦我把所有东西都放进了 正式的 S4 方法 ,似乎对 getClasses() 的标准环境有一些变化。用于查找类
setGeneric(
name="foo2",
signature="x",
def=function(x, ...) standardGeneric("foo2")
)
setMethod(
f="foo2",
signature=signature(x="missing"),
definition=function(
x,
where=.GlobalEnv
) {
if (is.null(where)) {
x <- getClasses()
} else {
x <- getClasses(where=where)
}
return(x)
}
)
[1] "foo2"
> foo2()
[1] "A"
> classes <- foo2(where=NULL)
> head(classes)
[1] "A" "(" ".environment" ".externalptr" ".name"
[6] ".NULL"
> "A" %in% classes
[1] TRUE

之前, "A" %in% foo1(where=NULL)FALSE ( 需要 ) 而 "A" %in% foo2(where=NULL)TRUE现在( 不需要 )。

任何想法如何 foo2()行为方式与 foo1() 完全相同?

编辑 2012-08-29

正如 Josh O'Brien 在下面的评论中指出的那样,这种变化可能是由懒惰的评估引起的。

调试 foo1()
debug(getClasses)
foo1(where=NULL)

您进入调试跟踪器;点击 <RETURN> 4次然后输入 get("where") :
Browse[2]> get("where")
<environment: namespace:base>

在控制台中,点击 <RETURN> 1 次 然后输入 evList :
Browse[2]> evList
[[1]]
<environment: namespace:base>

类型 Q退出当前调试运行

现在再次运行所有内容,但调试调用略有不同
foo1(where=NULL)

在控制台中,点击 <RETURN> 5次然后输入 evList :
Browse[2]> evList
[[1]]
<environment: namespace:methods>

现在输入 get("where") :
Browse[2]> get("where")
<environment: namespace:methods>

现在 where指向 namespace:methods
调试‘foo2()’
foo2(where=NULL)

您进入调试跟踪器;点击 <RETURN> 4次然后输入 get("where") :
Browse[2]> get("where")
<environment: namespace:base>

然后打 <RETURN> 1 次 然后输入 evList :
Browse[2]> evList
[[1]]
<environment: namespace:base>

类型 Q退出当前调试运行

现在再次运行所有内容,但调试调用略有不同
foo2(where=NULL)

命中 <RETURN> 5次然后输入 evList :
Browse[2]> evList
[[1]]
<environment: 0x02a68db8>

[[2]]
<environment: R_GlobalEnv>

# [OMITTED]

[[8]]
<environment: package:methods>
attr(,"name")
[1] "package:methods"
attr(,"path")
[1] "R:/Apps/LSQMApps/apps/R/R-2.14.1/library/methods"

[[9]]
<environment: 0x01e8501c>
attr(,"name")
[1] "Autoloads"

[[10]]
<environment: namespace:base>

现在输入 get("where") :
Browse[2]> get("where")
<environment: 0x02a68db8>

并注意 evList 的不同值和 where与之前的调试运行相比。类型 Q退出当前调试运行。

这对我来说似乎有些奇怪,但从语言设计者的角度来看可能是有道理的。一旦我知道如何明确设置 where,我可能会没事的指向与 namespace:methods 关联的环境.

最佳答案

再次吸取了一个众所周知的教训:明确总是好的;-)

感谢 Josh O'Brien而这个 post来自 Etiennebr我想我可以把这些碎片拼凑起来。

由于惰性求值和词法范围,我认为唯一的方法是真正 确保 getClasses()行为方式与从 .GlobalEnv 调用的方式相同或者从常规函数内部显式设置 where 的值到与 namespace:methods 相关联的环境打电话时getClasses()在正式的 S4 方法中。

要获取与命名空间关联的环境,这似乎有效:

env <- loadNamespace("methods")
> is.environment(env)
[1] TRUE

或者甚至更好:
env <- asNamespace("methods")
> is.environment(env)
[1] TRUE

这个环境正是我们需要指向的环境 where
setGeneric(
name="foo2",
signature="x",
def=function(x, ...) standardGeneric("foo2")
)
setMethod(
f="foo2",
signature=signature(x="missing"),
definition=function(
x,
where=.GlobalEnv
) {
if (is.null(where)) {
x <- getClasses(where=asNamespace("methods"))
} else {
x <- getClasses(where=where)
}
return(x)
}
)

> foo2()
[1] "A"
> classes <- foo2(where=NULL)
> head(classes)
[1] "(" ".environment" ".externalptr" ".name" ".NULL"
[6] ".Other"
> "A" %in% classes
[1] FALSE

关于r - `getClasses()` 中默认环境的模糊变化(标准函数与正式 S4 方法),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12166645/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com