2011-11-10 15 views
6

In qualche modo, a volte, che sto finendo in uno stato come questo:Strana differenza tra x e get ("x")?

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

non riesco a riprodurre in modo affidabile. Che tipo di cose potrei aver fatto di sbagliato nel mio codice C? Perché digitare x al prompt, ma non lo è get("x")? Qual è la differenza interna tra x e get("x")?

Eventuali suggerimenti molto apprezzati. Ho iniziato a vederlo da quando R 2.14.0 ma anche il mio codice C è cambiato.

EDIT: esempio riproducibile

// 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); 
} 

e per eseguirlo:

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") 
} 

L'uscita ottengo:

$ 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  
> 

Tutte le idee? Se la riga if (FALSE) A viene commentata, funziona correttamente. Per i test ripetuti, R deve essere avviato ogni volta fresco.

+0

Puoi approfondire 'il mio codice C è stato anche cambiando too'. Non ho familiarità con C, ma dovresti sicuramente postare il codice C, e attendere che @Dirk Eddelbuettel venga a conoscenza. A proposito, non posso replicare questo comportamento. – aL3xa

+0

@ aL3xa Aspetterò, grazie. –

+1

ma è molto più importante divulgare il tuo codice. =) – aL3xa

risposta

6

Questo in effetti si è rivelato essere il mio codice C. Sapevo che TRUELENGTH a volte è usato da R ma non ho pensato su CHARSXP. Quando il nome di una variabile è uguale ad un valore di carattere, TRUELENGTH di CHARSXP viene usato da R per mantenere un valore di hash interno, vedere main/envir.c. Il mio SET_TRUELENGTH su CHARSXP stava sbavando l'hash. Grazie a Simon Urbanek per averlo spiegato, e grazie per tutti i suggerimenti e le idee nei commenti.

Per dimostrare:

$ 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 

in cui il codice C per vedere il TrueLength del CHARSXP è:

// 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

Felice di sapere che l'hai bloccato! –

1

Il commento flusso è abbastanza vicino alla questione, e questo sembra difficile/impossibile da riprodurre:

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> 

Allo stesso modo tramite Littler:

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

Avremmo bisogno di vedere un esempio riproducibile. Se colpisce solo il tuo sistema, e soprattutto solo dopo, ad esempio, il tuo data.table è stato caricato, allora devi guardare lì. In qualche modo la logica del 'lookup symbol in enclosure frames' sembra essere stata colpita in testa.

+0

Sì, è probabile che si tratti di data.table, in fase di sviluppo. L'ho guardato;) ma sai come è a livello C a volte. Non è sempre facile trovare o sapere dove guardare. Guardando il registro di commit di R ho visto che '.GlobalEnv' è ora sottoposto a hash (a partire da maggio 2011), non sicuro di quale versione di R è stata modificata. Ci sono stati successivi commit da fare con R_UnboundValue. Quindi il valore hash potrebbe esserci, ma non è vincolato, in qualche modo, e questa è la differenza tra 'x' e' get ("x") '? Se riesco a stabilire cosa c'è che non va nell'oggetto, posso forse capire che cosa l'abbia causato. –

+0

Che dire di una x creata con setActiveBindings? – hadley

+0

@hadley Ho appena visto il tuo commento. Grazie, forse. Non ho ancora giocato con setActiveBindings. –

Problemi correlati