2011-11-10 149 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。 –

相關問題