2011-11-10 152 views
6

不知何故,有时,我的状态结束了这样的:x和get(“x”)之间的奇异区别?

> x 
[1] 1 2 3 
> get("x") 
Error in get("x") : object 'x' not found 
> x 
[1] 1 2 3 

我无法重现它可靠。我的C代码中可能会做什么错误?为什么会在提示符下输入x找到它,但是get("x")不是? xget("x")之间有什么不同?

任何提示非常赞赏。自R 2.14.0开始我就开始看到这个,但是我的C代码也一直在改变。

编辑:重复的例子,

// test.c 
#include <R.h> 
#include <Rdefines.h> 

SEXP test(SEXP df) 
{ 
    SEXP levels, s; 
    int j; 

    levels = getAttrib(VECTOR_ELT(df,0), R_LevelsSymbol); 
    Rprintf("levels %u, type %d, length %d, truelength %d\n", 
      levels,TYPEOF(levels),LENGTH(levels),TRUELENGTH(levels)); 

    for (j=0; j<length(levels); j++) { 
     s = STRING_ELT(levels,j); 
     Rprintf("%d %d %s %u %d %d\n", length(levels), TYPEOF(s), 
         CHAR(s), s, LENGTH(s), TRUELENGTH(s)); 
     SET_TRUELENGTH(s,1); // clobbers the 65, but why 65 ("A") there? 
     Rprintf("%d %d %s %u %d %d\n", length(levels), TYPEOF(s), 
         CHAR(s), s, LENGTH(s), TRUELENGTH(s)); 
    } 
    return(R_NilValue); 
} 

,并运行它:

R --vanilla 

system("R CMD SHLIB -otest.so test.c") 
dyn.load("test.so") 

if (FALSE) A  # needed for error to occur (!) 

DF <- data.frame(a = c("A", "Z"), b = 1:4) 
print(DF) 
.Call("test",DF) 
print(DF) 

A = data.frame() 
for (i in 1:100) { 
    cat(i,"") 
    assign(paste("v",i,sep=""),i) 
    get("A") 
} 

输出我得到:

$ R --vanilla  
R version 2.14.0 (2011-10-31) 
# [snip header] 
> system("R CMD SHLIB -otest.so test.c") 
gcc -std=gnu99 -I/usr/share/R/include  -fpic -std=c99 -O6 -Wall -Wno-unused -pedantic -c test.c -o test.o 
gcc -std=gnu99 -shared -o test.so test.o -otest.so -L/usr/lib/R/lib -lR 
> dyn.load("test.so") 
> 
> if (FALSE) A  # needed for error to occur (!) 
> 
> DF <- data.frame(a = c("A", "Z"), b = 1:4) 
> print(DF) 
    a b 
1 A 1 
2 Z 2 
3 A 3 
4 Z 4 
> .Call("test",DF) 
levels 151395176, type 16, length 2, truelength 0 
2 9 A 149596512 1 65 # why this 65 here? 
2 9 A 149596512 1 1 
2 9 Z 149596320 1 0 
2 9 Z 149596320 1 1 
NULL 
> print(DF) 
    a b 
1 A 1 
2 Z 2 
3 A 3 
4 Z 4 
> 
> A = data.frame() 
> for (i in 1:100) { 
+  cat(i,"") 
+  assign(paste("v",i,sep=""),i) 
+  get("A") 
+ } 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 Error in get("A") : object 'A' not found 
> 
> sessionInfo() 
R version 2.14.0 (2011-10-31) 
Platform: i686-pc-linux-gnu (32-bit) 

locale: 
[1] LC_CTYPE=en_GB.UTF-8  LC_NUMERIC=C    
[3] LC_TIME=en_GB.UTF-8  LC_COLLATE=en_GB.UTF-8  
[5] LC_MONETARY=en_GB.UTF-8 LC_MESSAGES=en_GB.UTF-8 
[7] LC_PAPER=C     LC_NAME=C     
[9] LC_ADDRESS=C    LC_TELEPHONE=C    
[11] LC_MEASUREMENT=en_GB.UTF-8 LC_IDENTIFICATION=C  

attached base packages: 
[1] stats  graphics grDevices utils  datasets methods base  
> 

任何想法?如果if (FALSE) A行被注释掉,那么它工作正常。对于重复测试,R必须每次都重新开始。

+0

你能否详细说明'我的C代码也已经改变too'。我对C不熟悉,但是您绝对应该发布C代码,并等待@Dirk Eddelbuettel全面进入。顺便说一句,我不能复制这种行为。 – aL3xa

+0

@ aL3xa我会等,谢谢。 –

+1

但是揭露你的代码更为重要。 =) – aL3xa

回答

6

这确实是我的C代码。我知道TRUELENGTH有时被R使用,但我没有考虑过CHARSXP。当变量名称与某些字符值相同时,CHARSXP的TRUELENGTH被R用来保存内部散列值,请参阅main/envir.c。 CHARSXP上的SET_TRUELENGTH正在破坏哈希。感谢Simon Urbanek解释这一点,并感谢评论中的所有提示和想法。

为了证明:

$ R --vanilla 
R version 2.14.0 (2011-10-31) 

> system("R CMD SHLIB -otest.so test.c") 
> dyn.load("test.so") 
> truelength = function(x)invisible(.Call("truelength",x)) 
> 
> truelength("A") 
'A' has length 1 and truelength 0 
> truelength("ABC") 
'ABC' has length 3 and truelength 0 
> A=123 
> truelength("A") 
'A' has length 1 and truelength 65 # 65 is the HASHPRI, for bound variable A 
> truelength("ABC") 
'ABC' has length 3 and truelength 0 # no variable ABC so truelength unused 
> ABC=456 
> truelength("ABC") 
'ABC' has length 3 and truelength 17763 # now ABC symbol is bound 
> 
> foo = 7 
> truelength("foo")    
'foo' has length 3 and truelength 27999 # bound 
> truelength("bar")    
'bar' has length 3 and truelength 0  # not bound 
> .Internal(inspect("foo")) 
@876eb08 16 STRSXP g0c1 [NAM(2)] (len=1, tl=0) # tl=0 of STRSXP vector 
    @81759e8 09 CHARSXP g0c1 [gp=0x21] "foo"  # tl of CHARSXP not shown by inspect 

所在的C代码看CHARSXP的TRUELENGTH是:

// test.c 
#include <R.h> 
#include <Rdefines.h> 

SEXP truelength(SEXP v) 
{ 
    SEXP s = STRING_ELT(v,0); 
    Rprintf("'%s' has length %d and truelength %d\n", 
        CHAR(s), LENGTH(s), TRUELENGTH(s)); 
    return(R_NilValue); 
} 
+0

很高兴知道你把它钉住了! –

1

注释流是非常接近的问题,这似乎难以/不可能再现:

R> x <- 1L:3L 
R> x 
[1] 1 2 3 
R> get("x") 
[1] 1 2 3 
R> matt <- function() { y <- 7L:9L; get("y") } 
R> matt() 
[1] 7 8 9 
R> 

同样通过利特勒:

[email protected]:~$ r -e 'x <- 1L:3L; print(get("x"))' 
[1] 1 2 3 
[email protected]:~$ 

我们需要看到重复的例子。如果它只是碰到你的系统,特别是在你的data.table已经被加载之后,那么你必须去看看那里。不知何故,封闭框架逻辑中的“查找符号”似乎已被击中头部。

+0

是的,这可能与data.table有关。我一直在看它;)但你知道它有时在C级是如何。找到或知道去哪里看并不总是很容易。看看R的提交日志,我看到'.GlobalEnv'现在已经散列(截至2011年5月),不确定哪个版本的R所做的更改。随后提交了有关R_UnboundValue的提交。那么哈希值可以在那里,但它不受限制,这是'x'和'get(“x”)'之间的区别吗?如果我能确定这个对象有什么问题,我可以找出是什么原因造成的。 –

+0

用setActiveBindings创建的x怎么样? – hadley

+0

@hadley刚刚看到您的评论。谢谢,也许吧。我还没有玩过setActiveBindings。 –

相关问题